Introduction
Bulk RNA sequencing data on 24 pre-treatment breast cancer tumours
performed by Wu et al. [1] was downloaded from
GEO with accession GSE176078,
and associated
publication.
geo_id <- "GSE176078"
This dataset was sequenced using Illumina NextSeq 500 (Homo sapiens),
submitted on Apr 15 2014.
Breast cancers are clinically stratified based on:
- expression of the estrogen receptor (ER),
- expression of the progesterone receptor (PR), and
- overexpression of HER2 (or amplification of HER2
gene ERBB2)
This results in the following three clinical
subtypes within this dataset:
- Luminal ie. ER+; (ER+, PR+/-)
- HER2+; (HER2+, ER+/-, PR+/-)
- Triple Negative ie. TNBC; (ER-, PR-,
HER2-)
Breast cancers are also stratified on bulk transcriptomic profiling
via PAM50 gene signatures [2] describing five
molecular subtypes: Luminal A, Luminal B,
HER2-enriched, Basal-like, and Normal-like.
The ~70-80% concordance between clinical and molecular subtypes
motivated this study to improve functional understanding of breast
cancer in a broader and more coherent sense.
For this study, the clinical subtype conditions classified are as
follows:
HER2+ ; (HER2+, ER-,
PR+/-)
HER2+/ER+ ; (HER2+, ER+,
PR+/-)
ER+ ; (HER2-, ER+,
PR+/-)
TNBC ; (HER2-, ER-,
PR-)
The distribution of clinical subtypes across the 24 samples is shown
in table 1.
Table 1: Clinical breast cancer subtype splits in our dataset
| |
Count |
Percent |
| HER2+ |
2 |
8.33 |
| HER2+/ER+ |
2 |
8.33 |
| TNBC |
8 |
33.33 |
| ER+ |
12 |
50.00 |
| Total |
24 |
100.00 |
This leads to
- 16.6666667% of samples containing
HER2 expression,
and
- 58.3333333% of samples containing
ER expression,
With the overlaps giving us
- 50% of those with
HER2 expressed also had
ER expressed,
- 14.2857143% of those with
ER expressed also had
HER2 expressed.
The raw counts were cleaned, mapped to HUGO Gene Nomenclature Committee
(HGNC) Symbols, and normalized to produce final counts. Of the
original 58387 genes, we were able to map and produce
28712 unversioned, unique genes, of which filtering
outliers (keeping genes present in a minimum of 12 samples)
resulted in 14800 genes remaining.
The density plot shows the distribution of the cleaned, filtered, and
normalized counts per million across all samples (varying colours).
Figure 1: Smoothing density of filtered and
normalized CPM counts for 24 samples across four clinical subtypes of
breast cancer tissue. Counts were filtered with edgeR’s
cpm() thresholded at a minimum sum of 12 CPM across samples
for each gene. Counts were normalized with edgeR’s
DGEList() across all four clinical subtypes. Normalization
factors were calculated via TMM.
Dispersion was calculated using edgeR to describe
deviation of variance from the mean. The Biological Coefficient of
Variation (BCV) is dispersion-squared, and represents the mean-variance
relationship among genes.
Figure 2: Biological Coefficient of Variation
(Dispersion squared) for 24 samples across four clinical subtypes of
breast cancer tissue gene-wise. Dispersion was calculated using
edgeR’s plotBCV() on the model designed across
all four clinical subtypes.
The normalized counts were modeled by two designs. The first
being an aggregate design considering all clinical subtypes as distinct,
ie. HER2+/ER+, HER2+, ER+, and TNBC.
The second being a split binary-pairing model combining the two separate
classification subtypes, ie. HER2+/- and ER+/- as a
binary pair. The separate model designs represented different
perspectives on labeling the data and allow for more specific or generic
conclusions.
# aggregate model design
model_design <- model.matrix(~ types_df$subtype)
# split model design (binary pairs)
splt_model_design <- model.matrix(~ types_df$her2 + types_df$er)
The Quasi-Likelihood Model from edgeR was
used to produce Quasi-Likelihood Fits for each model
design, at which point differential expression was calculated across the
models.
# normalized counts grouped by clinical subtype
d <- DGEList(counts=norm_matrix,
group=types_df$subtype)
# estimate dispersion on subtype model design
d_ <- estimateDisp(d, model_design)
qlfit <- glmQLFit(d_, model_design)
# in parallel, estimate dispersion on binary pairing model design
d_splt <- estimateDisp(d, splt_model_design)
qlfit_splt <- glmQLFit(d_splt, splt_model_design)
# fit subtype model design
qlf.subtypes <- glmQLFTest(qlfit)
# fit split model design
qlf.her2p <- glmQLFTest(qlfit_splt,
coef='types_df$erTRUE')
qlf.erp <- glmQLFTest(qlfit_splt,
coef='types_df$her2TRUE')
The Benjamini-Hochberg method for false discovery
was used to correct p-values to classify the resulting genes that passed
correction for differential expression in their respective models,
producing the following volcano plots. Note that only the aggregate
design and ER specific expression models are shown since no
genes passed correction for the HER2 specific design.
Figure 3: Volcano Plot for significantly
differentially expressed genes in 24 samples across four clinical
subtypes of breast cancer tissue (aggregate design). Differential
expression was calculated across the aggregate model design across all
four clinical subtypes. Significant before correction is represented by
p < 0.05, with significant after correction being FDR <
0.05.
The aggregate model highlights in red CD207, MKX,
and ANXA8 as genes significantly differentially expressed after
correction for false discovery.
Figure 4: Volcano Plot for significantly
differentially expressed genes in 24 samples across binary
over-expression of ER clinical subtypes of breast cancer tissue (split
design). Differential expression was calculated across ER expression
design. Significant before correction is represented by p < 0.05,
with significant after correction being FDR < 0.05.
The split model in terms of ER over-expression highlights in
red EPHA3, KCNMB2, CLEC1B, CYP2G1P,
CDH26, CASC3, TFF3, RAPGEFL1,
MSL1, MUC4, and THRA as genes significantly
differentially expressed after correction for false discovery.
Using these models, non-thresholded gene-sets can be pulled by
ranking according to -log(p-values) and signing according to the log
fold-change.
# create non-thresholded gene sets
# across all clinical subtypes
nt_geneset <- qlf.subtypes$table
nt_geneset[,"Rank"] <- -log10(nt_geneset$PValue) * sign(nt_geneset$logFC)
nt_geneset <- nt_geneset[order(nt_geneset$Rank, decreasing=TRUE),]
# across ER over-expression
er_geneset <- qlf.erp$table
er_geneset[,"Rank"] <- -log10(er_geneset$PValue) * sign(er_geneset$logFC)
er_geneset <- er_geneset[order(er_geneset$Rank, decreasing=TRUE),]
The ranked gene-sets are saved as .rnk files for further
analysis in the remainder of this report.
# for the aggregate clinical subtype model
# create a separate ranks matrix with only gene name and rank
geneset_ranks <- cbind(rownames(nt_geneset), nt_geneset[,"Rank"])
colnames(geneset_ranks) <- c("GeneName", "Rank")
ranked_geneset_filepath <- file.path(getwd(),
geo_id,
"ag_ranks.rnk")
# if the file does not exist already
if (!file.exists(ranked_geneset_filepath)) {
# write this matrix to the file
write.table(geneset_ranks,
ranked_geneset_filepath,
quote=FALSE,sep="\t",row.name=FALSE)
}
# for the ER over-expression model
# create a separate ranks matrix with only gene name and rank
geneset_er_ranks <- cbind(rownames(er_geneset), er_geneset[,"Rank"])
colnames(geneset_er_ranks) <- c("GeneName", "Rank")
ranked_er_geneset_filepath <- file.path(getwd(),
geo_id,
"er_ranks.rnk")
# if the file does not exist already
if (!file.exists(ranked_er_geneset_filepath)) {
# write this matrix to the file
write.table(geneset_er_ranks,
ranked_er_geneset_filepath,
quote=FALSE,sep="\t",row.name=FALSE)
}
Table 2: Gene Ranks for aggregate model design across HER2+/ER+, HER2+, ER+, and TNBC clinical subtypes of breast cancer.
| GeneName |
Rank |
| CD207 |
5.42322474118346 |
| MKX |
5.39993135731511 |
| ANXA8 |
5.12680098507216 |
| HES4 |
4.03194218398041 |
| PCSK1 |
3.99254046943472 |
| UCA1 |
3.73274435594156 |
Table 3: Gene Ranks for split model design across ER +/- overexpression as a clinical subtype classifier of breast cancer.
| GeneName |
Rank |
| EPHA3 |
7.40069275730718 |
| KCNMB2 |
6.31726250155973 |
| CLEC1B |
6.10558550086033 |
| CYP2G1P |
5.80136230063012 |
| CDH26 |
5.28827272752202 |
| CASC3 |
5.10530649248159 |
The first five genes are displayed in the tables above for the two
model designs of interest.
Non-Thresholded
Gene-Set Enrichment Analysis
Using the GSEA command-line interface .jar for
compatibility of using GSEA with R, we can download the desired gene-set
file from the Bader Lab.
The code below is adapted from Ruth Isserlin [3].
# variable names for easier modification
gsea_jar = "~/GSEA_4.3.2/gsea-cli.sh"
working_dir = "~/projects/GSE176078"
output_dir = "~/projects/GSE176078/gsea"
analysis_name_ag = "clinical subtypes"
analysis_name_er = "ER over-expression"
ag_rnk_file = "ag_ranks.rnk"
er_rnk_file = "er_ranks.rnk"
# the March 1st release (latest at this point)
gmt_url = "http://download.baderlab.org/EM_Genesets/March_01_2025/Human/symbol/"
#use the non-filtered gmt
gmt_files <- list.files(path = output_dir, pattern = "\\.gmt")
if (length(gmt_files) == 0) {
# download the desired gene-set file
filenames = getURL(gmt_url)
tc = textConnection(filenames)
contents = readLines(tc)
close(tc)
# filter based on the following specifications:
# + Gene Ontology : Biological Processes terms,
# + include All Pathways
# - WikiPathways (PFOCR), and
# - GO IEA (electronic annotations)
rx = gregexpr("(?<=<a href=\")(.*.GOBP_AllPathways_noPFOCR_no_GO_iea.*.)(.gmt)(?=\">)",
contents, perl = TRUE)
gmt_file = unlist(regmatches(contents, rx))
dest_gmt_file <- file.path(output_dir, gmt_file)
# if the gmt file has not already been downloaded
if(!file.exists(dest_gmt_file)){
# download the specified release from the URL
download.file(
paste(gmt_url,gmt_file,sep=""),
destfile=dest_gmt_file
)
} else {
dest_gmt_file <- gmt_files[1]
}
}
# generate the command for the aggregate clinical subtype model
cmd <- paste("", gsea_jar,
"GSEAPreRanked -gmx", dest_gmt_file,
"-rnk" ,file.path(working_dir, ag_rnk_file),
"-collapse false -nperm 1000 -scoring_scheme weighted",
"-rpt_label ", analysis_name_ag,
" -plot_top_x 20 -rnd_seed 12345 -set_max 200",
" -set_min 15 -zip_report false ",
" -out", output_dir,
" > gsea_output_ag.txt", sep=" ")
# if the output folder does not already exist
if (length(list.files(path=output_dir,
pattern="^clinical.GseaPreranked")) == 0) {
system(cmd) # run the cmd
}
# and generate the command for the ER over-expression classifier model
cmd <- paste("", gsea_jar,
"GSEAPreRanked -gmx", dest_gmt_file,
"-rnk" ,file.path(working_dir, er_rnk_file),
"-collapse false -nperm 1000 -scoring_scheme weighted",
"-rpt_label ", analysis_name_er,
" -plot_top_x 20 -rnd_seed 12345 -set_max 200",
" -set_min 15 -zip_report false ",
" -out", output_dir,
" > gsea_output_er.txt", sep=" ")
# if the output folder does not already exist
if (length(list.files(path=output_dir,
pattern="^ER.GseaPreranked")) == 0) {
system(cmd) # run the cmd
}
What method did you
use?
I chose to use GSEA’s PreRanked Analysis since I had
familiarity with it through my journal entry and found it to be very
informative on completion of the analysis. It was also flexible in terms
of using whichever gene matrix transposed gene-set file I wanted, which
meant I could redo the analysis programmatically if I needed to try
again with a different or updated gene-set.
What gene-sets did
you use? (Specify versions and cite your methods)
I chose to use the the Human gene-set from the BaderLab released
on March 1st, 2025. The gene-sets were developed using the
latest version of GO Human annotations on December 21, 2025, which means
we are using the release dated most recently before this. As such, it
includes
GO:BP :
Gene Ontology: Biological Processes ; version
225 released 24 October, 2024
There is an option to include PFOCR, which is
WikiPathways, however I did not include this since I
performed the analysis only using GO:BP first and found it
to be sufficient for my needs in terms of this analysis.
Summarize your
enrichment results
There are a lot of individual plots available for specific terms.
First, the following plots agree with our volcano plots to give us
more confidence in the remaining results.

Figure 5: Normalized Enrichment Score and Significance plots for both
model designs. a, Aggregate model design, ie. across
all clinical subtypes presented in this study; HER2+,
HER2+/ER+, ER+, and TNBC. b,
ER over-expression subtype classified by either over-expressed
ER, or lack thereof. Produced by the GSEA PreRanked Analysis.
Significance is determined via Benjamini-Hochberg correction for False
Discovery Rate, p < 0.05.
I read in the resulting csv files from the GSEA reports.
ag_neg <- read.csv2(file.path(ag_dir, "gsea_report_for_na_neg_1743386287182.tsv"),
header=TRUE, sep="\t")
ag_pos <- read.csv2(file.path(ag_dir, "gsea_report_for_na_pos_1743386287182.tsv"),
header=TRUE, sep="\t")
er_neg <- read.csv2(file.path(er_dir, "gsea_report_for_na_neg_1743386532278.tsv"),
header=TRUE, sep="\t")
er_pos <- read.csv2(file.path(er_dir, "gsea_report_for_na_pos_1743386532278.tsv"),
header=TRUE, sep="\t")
I display the top hits for both models, both positively and
negatively correlated.
Table 4: Negatively correlated top gene-set hits for aggregate model design across HER2+, HER2+/ER+, ER+, and TNBC.
| x |
| 17Q12 COPY NUMBER VARIATION SYNDROME%WIKIPATHWAYS_20250210%WP5287%HOMO SAPIENS |
| PHOSPHODIESTERASES IN NEURONAL FUNCTION%WIKIPATHWAYS_20250210%WP4222%HOMO SAPIENS |
| CELLULAR COMPONENT ASSEMBLY INVOLVED IN MORPHOGENESIS%GOBP%GO:0010927 |
| REGULATION OF EXTRACELLULAR MATRIX ASSEMBLY%GOBP%GO:1901201 |
| CELLULAR ANATOMICAL ENTITY MORPHOGENESIS%GOBP%GO:0032989 |
| MYOTUBE DIFFERENTIATION%GOBP%GO:0014902 |
Table 5: Positively correlated top gene-set hits for aggregate model design across HER2+, HER2+/ER+, ER+, and TNBC.
| x |
| MAJOR PATHWAY OF RRNA PROCESSING IN THE NUCLEOLUS AND CYTOSOL%REACTOME%R-HSA-6791226.5 |
| INFLUENZA VIRAL RNA TRANSCRIPTION AND REPLICATION%REACTOME DATABASE ID RELEASE 91%168273 |
| RRNA PROCESSING IN THE NUCLEUS AND CYTOSOL%REACTOME%R-HSA-8868773.5 |
| PROTEIN SYNTHESIS: LEUCINE%SMPDB%SMP0111873 |
| EUKARYOTIC TRANSLATION ELONGATION%REACTOME%R-HSA-156842.4 |
| PROTEIN SYNTHESIS: LYSINE%SMPDB%SMP0111874 |
Table 6: Negatively correlated top gene-set hits for ER over-expression model design.
| x |
| HALLMARK_INTERFERON_ALPHA_RESPONSE%MSIGDBHALLMARK%HALLMARK_INTERFERON_ALPHA_RESPONSE |
| HALLMARK_INTERFERON_GAMMA_RESPONSE%MSIGDBHALLMARK%HALLMARK_INTERFERON_GAMMA_RESPONSE |
| NUCLEAR DNA REPLICATION%GOBP%GO:0033260 |
| B CELL MEDIATED IMMUNITY%GOBP%GO:0019724 |
| IMMUNOGLOBULIN MEDIATED IMMUNE RESPONSE%GOBP%GO:0016064 |
| ASSEMBLY OF COLLAGEN FIBRILS AND OTHER MULTIMERIC STRUCTURES%REACTOME%R-HSA-2022090.5 |
Table 7: Positively correlated top gene-set hits for ER over-expression model design.
| x |
| REGULATION OF VASOCONSTRICTION%GOBP%GO:0019229 |
| CELL-CELL ADHESION MEDIATED BY CADHERIN%GOBP%GO:0044331 |
| PHYSIOLOGICAL AND PATHOLOGICAL HYPERTROPHY OF THE HEART%WIKIPATHWAYS_20250210%WP1528%HOMO SAPIENS |
| SMOOTH MUSCLE CONTRACTION%GOBP%GO:0006939 |
| FATTY ACID DERIVATIVE BIOSYNTHETIC PROCESS%GOBP%GO:1901570 |
| FOXO-MEDIATED TRANSCRIPTION OF OXIDATIVE STRESS, METABOLIC AND NEURONAL GENES%REACTOME DATABASE ID RELEASE 91%9615017 |
** Show some enrichment plots of interest! …
a, Aggregate model design, ie. across all clinical
subtypes presented in this study; HER2+, HER2+/ER+,
ER+, and TNBC. b, ER over-expression
subtype classified by either over-expressed ER, or lack
thereof. Produced by the GSEA PreRanked Analysis. Significance is
determined via Benjamini-Hochberg correction for False Discovery Rate,
p < 0.05.
http://localhost:8787/files/projects/GSE176078/gsea/clinical.GseaPreranked.1743386287182/enplot_MAJOR_PATHWAY_OF_RRNA_PROCESSING_IN_THE_NUCLEOLUS_AND_CYTOSOL_REACTOME_R-HSA-6791226.5_1.png

Figure 6: Some enrichment plots for both model designs.
a, Aggregate model design, ie. across all clinical
subtypes presented in this study; HER2+, HER2+/ER+,
ER+, and TNBC. Presented is the enrichment plot for
rRNA processing in the nucleus and cytosol reactome. b,
ER over-expression subtype classified by either over-expressed
ER, or lack thereof. Presented is the enrichment plot of
cell-cell adhesion mediated cadherin binding. Produced by the GSEA
PreRanked Analysis. Statistics and metrics are described on the GSEA
website.
How do these results
compare to the results from the thresholded analysis in Assignment 2?
Compare qualitatively.
Interferons and cadherin-binding are
familiar terms from assignment 2. Although the depth of detail we
achieved was much less in assignment 2, and not only that, we had less
scope due to the thresholds on our gene-sets. There are some
similarities, and some differences, which is to be expected.
Is this a straight
forward comparison? Why or Why not?
No, since the versions of data we are using is different. Also, the
thresholded analysis does not contain as much information, and although
we have gene-set size information available in our non-thresholded
analysis results, it is not straight-forward.
Visualizing Gene-Set
Enrichment Analysis in Cytoscape
Similarly to our analysis using GSEA, we will perform our analysis
using Cytoscape via R code.
The code below is adapted from Ruth Isserlin [4].
We ensure to use the original gene-matrix transposed file so as not
to hinder our analysis with the filtering present in the output
.gmt from GSEA.
#use the non-filtered gmt
gmt_files <- list.files(path = output_dir, pattern = "\\.gmt")
# get the details on the files
details = file.info(file.path(output_dir,gmt_files))
# order from newest to oldest
details = details[with(details, order(as.POSIXct(mtime),decreasing = TRUE)), ]
#use the newest file:
gmt_gsea_file <- row.names(details)[1]
ag_edb <- file.path(ag_dir, "edb")
er_edb <- file.path(er_dir, "edb")
ag_res_edb <- file.path(ag_edb, "results.edb")
er_res_edb <- file.path(er_edb, "results.edb")
ag_ranks <- file.path(ag_edb, "ag_ranks.rnk")
er_ranks <- file.path(er_edb, "er_ranks.rnk")
# build the class file for aggregate design
ag_cls = "~/projects/GSE176078/ag.cls"
if (!file.exists(ag_cls)) {
# num of samples of each class
cat(as.character(subtype_counts[1:4,1]),sep = " ",file=ag_cls,append=TRUE)
cat("\n", file=ag_cls, append=TRUE)
# names of each class
cat(c("#", "HER2+", "HER2+/ER+", "TNBC", "ER+"), sep = " ",file=ag_cls,append=TRUE)
cat("\n", file=ag_cls, append=TRUE)
# ordered name for each sample
cat(types_df$subtype, sep = " ",file=ag_cls,append=TRUE)
cat("\n", file=ag_cls, append=TRUE)
}
We must ensure cytoscape is running for the next sections of code. If
everything is working properly, there will be a successful message from
Cytoscape after we ping!
# define docker base url's
current_base = "host.docker.internal:1234/v1"
.defaultBaseUrl <- "http://host.docker.internal:1234/v1"
cytoscapePing(base.url = current_base)
You are connected to Cytoscape!
We are currently using Cytoscape version v1,
3.10.3.
# function to upload a local file to the host machine
to_cytoscape <- function(local_path) {
bname <- basename(local_path)
r <- POST(
url =
paste('http://host.docker.internal:1234/enrichmentmap/textfileupload?fileName=',
bname, sep=""),
config = list(),
body = list(file = upload_file(local_path)),
encode = "multipart",
handle = NULL
)
content(r,"parsed")$path
}
# starting with the aggregate design model,
# upload local files and record the host path
ag_res_edb <- to_cytoscape(ag_res_edb)
ag_ranks <- to_cytoscape(ag_ranks)
gmt <- to_cytoscape(gmt_gsea_file)
ag_cls <- to_cytoscape(ag_cls)
# expr file ?
# and upload files for the ER over-expression model
er_res_edb <- to_cytoscape(er_res_edb)
er_ranks <- to_cytoscape(er_ranks)
Create an Enrichment
map
pval <- 0.05
qval <- 0.05
sim <- 0.375
sim_metric <- "COMBINED" # or JACCARD
ag_network <- paste("aggregate", pval, qval, sep="_")
em_cmd = paste('enrichmentmap build analysisType="gsea" gmtFile=',
gmt,
'pvalue=', pval,
'qvalue=', qval,
'similaritycutoff=', sim,
'coefficients=', sim_metric,
'ranksDataset1=', ag_ranks,
'enrichmentsDataset1=', ag_res_edb,
'filterByExpressions=false',
# 'expressionDataset1=',expression_file_fullpath,
'classDataset1=', ag_cls,
# 'gmtFile=', gmt,
sep=" ")
# fetch the suid of the newly created network
ag_resp <- commandsGET(em_cmd, base.url = current_base)
# check if the cmd was successful or failed
if (grepl(pattern="Failed", ag_resp)) {
paste(ag_resp)
} else {
ag_suid <- ag_resp
}
curr_names <- getNetworkList(base.url = current_base)
if (ag_network %in% curr_names) {
ag_network <- paste(ag_suid, ag_network, sep="_")
}
resp <- renameNetwork(title = ag_network,
network = as.numeric(ag_suid),
base.url = current_base)
And, for the ER over-expression model, I create another enrichment
map.
pval <- 0.05
qval <- 0.05
sim <- 0.375
sim_metric <- "COMBINED" # or JACCARD
er_network <- paste("er", pval, qval, sep="_")
em_cmd = paste('enrichmentmap build analysisType="gsea" gmtFile=',
gmt,
'pvalue=', pval,
'qvalue=', qval,
'similaritycutoff=', sim,
'coefficients=', sim_metric,
'ranksDataset1=', er_ranks,
'enrichmentsDataset1=', er_res_edb,
'filterByExpressions=false',
sep=" ")
# fetch the suid of the newly created network
er_resp <- commandsGET(em_cmd, base.url = current_base)
# check if the cmd was successful or failed
if (grepl(pattern="Failed", er_resp)) {
paste(er_resp)
} else {
er_suid <- er_resp
}
curr_names <- getNetworkList(base.url = current_base)
if (er_network %in% curr_names) {
er_network <- paste(er_suid, er_network, sep="_")
}
er_resp <- renameNetwork(title = er_network,
network = as.numeric(er_suid),
base.url = current_base)
How many nodes and
how many edges in the resulting map?
Our enrichment map network for the aggregate model design across all
four clinical subtypes of breast cancer presented, HER2+/ER+,
HER2+, ER+, and TNBC, has:
- # nodes :
364
- # edges :
2768
And the ER over-expression design across ER+/-, has:
- # nodes :
82
- # edges :
201
What thresholds
were used to create this map? (make sure to record all thresholds)
I used the following thresholds for both networks:
- p-value :
0.05
- q-value :
0.05
- similarity threshold :
0.375
I used the COMBINED similarity metric for these
maps.
Include a
screenshot of your network prior to manual layout.
Shown are the networks prior to manual layout. Note that this section
could not be programmatically retrieved and displayed due to the
limitations of using Cytoscape in R with Docker.
Both layouts are very messy before adjustment, and purely for
demonstrative purposes.
Figure 7: Initial network layout for aggregate
model design; HER2+, HER2+/ER+, ER+, and
TNBC. Generated using Cytoscape via RCy3. p-value < 0.05,
q-value < 0.05, similarity threshold < 0.375 with a combined
similarity metric.
Figure 8: Initial network layout for ER
over-expression model; ER+/-. Generated using Cytoscape via
RCy3. p-value < 0.05, q-value < 0.05, similarity threshold <
0.375 with a combined similarity metric.
Annotate your
Network
Annotating the network is where the manual work begins and the
figures start to look readable.
What parameters did
you use to annotate the network? (make sure to list the default
parameters you are using as well)
I added a class file in the GSEA format to add information about each
sample’s classification according to the aggregate clinical subtype
design, however I did not really see it present in the network.
I used the AutoAnnotate additional application to
annotate using Gene-Set Descriptions. I selected the
‘Layout Network to avoid cluster overlap’ and adjusted some of the
labels that were overlapping.
The nodes are colour-scaled by FDR q-value with
darker-red nodes having values closer to 0.00, and lighter-red nodes
having values closer to 0.05.
Cut-Off Values:
- P-value: 0.05
- FDR Q-value: 0.05
- Jaccard Overlap Combined: 0.375
- Test used: Jaccard Overlap Combined Index (k constant = 0.5)
Data Sets:
- Dataset 1
- Gene Sets File:
…/em_fileupload_16120623913225671898/em_11162267974427327696_
Human_GOBP_AllPathways_noPFOCR_no_GO_iea_March_01_2025_symbol.gmt
- Data Files:
…/em_fileupload_16120623913225671898/em_6205993452311517617_results.edb
- Ranks File:
…/em_fileupload_16120623913225671898/em_13925529101006825111_ag_ranks.rnk
- Positive Phenotype: UP
- Negative Phenotype: DOWN
Collapse your network
to a theme network.
For this section, I generated two themed networks for each of the
model designs.
First, I generated a summary network to show a more concise and
simple design highlighting the major connection points in this
network.
Figure 11: Summary themed network for aggregate
model design; HER2+, HER2+/ER+, ER+, and
TNBC. Generated using Cytoscape via RCy3, cleaned using
AutoAnnotate application in the Cytoscape interface to generate a
Summary network. p-value < 0.05, q-value < 0.05, similarity
threshold < 0.375 with a combined similarity metric.
Next, I generated a clustering at the most generic level for the
aggregate design network.
Figure 12: Generic clustering network for
aggregate model design; HER2+, HER2+/ER+,
ER+, and TNBC. Generated using Cytoscape via RCy3,
cleaned using AutoAnnotate application in the Cytoscape interface to
generate the most generic clustering available. p-value < 0.05,
q-value < 0.05, similarity threshold < 0.375 with a combined
similarity metric.
Figure 13: Summary clustering network for ER
over-expression model design; ER+/-. Generated using Cytoscape
via RCy3, cleaned using AutoAnnotate application in the Cytoscape
interface to generate a Summary network. p-value < 0.05, q-value <
0.05, similarity threshold < 0.375 with a combined similarity
metric.
Figure 14: Generic clustering network for ER
over-expression model design; ER+/-. Generated using Cytoscape
via RCy3, cleaned using AutoAnnotate application in the Cytoscape
interface to generate the most generic clustering available. p-value
< 0.05, q-value < 0.05, similarity threshold < 0.375 with a
combined similarity metric.
What are the major
themes present in this analysis?
Pretty clearly for the aggregate model design, the major theme is
protein synthesis processes. The most generic level of grouping had no
real effect on the nodes seemingly separate from the most central
grouping, and so grouped the most related gene-sets into
Protein Synthesis Processes.
This particular grouping majorly combines
SRP Protein Synthesis,
Nuclear Export Sumoylation,
Process Purine Catabolism, and
Strand DNA Templating, along with
de novo folding, small subunit assembly,
Tricistronic rRNA SSU, among a few others.
Apart from this major theme, the separate groups are fairly separate,
although some possible mechanisms present themselves as interesting,
such as the relation of Thymic IL2 1 Pathway and
Spindle Checkpoint Chromosome to breast cancerous subtype
differences.
For the ER over-expression model design, the major theme appears to
be the Electron Transport Process, along with
Phospholipid Phagocytosis and
Strand Nuclear DNA.
Electron Transport Process groups
Glycogenesis Type Deficiency,
Process Diphosphate Metabolic, and
Coupled Electron Transport.
Do they fit with
the model?
It is not very informative to say that
Protein Synthesis Processes fit as a determination in
distinguishing different clinical subtypes of breast cancer.
HER2 and ER over-expression or lack thereof classify
these subtypes, and so it seems natural that protein synthesis is
involved.
Similarly, the Electron Transport Process is hallmark to
the entirety of cellular function. As to how it fits with ER
over-expression or lack thereof in breast cancerous subtypes is
unknown.
Are there any novel
pathways or themes?
There are some novel pathways and themes, like that of
Thymic IL2 1 Pathway and
Spindle Checkpoint Chromosome which can be associated with
possible mechanisms of breast cancer. As to how these separate the
clinical subtypes of breast cancer is novel, but possible. Interleukin
inflammation can contribute to environments conducive to cancerous
growth and proliferation, similarly with problems in the cell cycle like
that of spindle checkpoint(s).
Skin Epidermis Development seems quite far off from
breast cancer. I am assuming metastases can be common for one reason or
another, but it is very difficult to characterize this small grouping as
being related to the clinical subtypes of our interest.
For the ER over-expression, it seems most of the pathways, even
despite having only a few nodes, are rather relevant to the relative
realm of breast cancerous pathology.
Interpretation
Do the enrichment
results support conclusions or mechanisms discussed in the original
paper?
The original paper included this enrichment analysis of their
single-cell RNA sequencing samples. This Gene-Set Enrichment Analysis
was performed using ClusterProfiler with gene-sets from the MSigDB
HALLMARK collection. p-values < 0.05 were adjusted using
Bonferroni.
Figure 15: Gene-Set Enrichment Analysis
performed by the original publishers Wu. et al (2021)
My aggregate model design solely agrees with the findings of the
publication on Mitotic Spindle. The remainder of my network
does not agree with the findings whatsoever.
Similarly, my ER over-expression design lists
Hallmark Interferon Response in agreement with the
publication. Other than that, there is little agreement.
How do these
results differ from the results you got in Assignment 2 thresholded
methods?
In assignment 2, my enrichment results mentioned
Interferons, and Cadherin-binding, but nothing
else is too similar. Apart from the very generic conclusions being
Protein Synthesis Processes and
Electron Transport Processes.
Can you find
evidence, ie. publications, to support some of the results that you
see?
Not conclusively. Although there is always correlative evidence,
especially in a field so researched as breast cancer, I do not believe
the evidence is substantial enough to really say anything at this point.
The network outcomes are too generic for any conclusions to be drawn
from this.
How does the
evidence support your result?
I struggled to find evidence to support these results since they are
so generic.
Detailed View of
Results
I chose to analyze the three significantly differentially expressed
genes in the ER over-expression model: ANXA8, MKX, and
CD207.
I found a network containing both ANXA8 and CD207
under the epidermis development GO biological process.
Figure 16: Network for epidermis development
which includes both ANXA8 and CD207; two of the three significant genes
in ER over-expression. Pulled by using the STITCH protein query on the
respective genes of interest on Cytoscape.
They interact through hsa-mir-205, which is a micro RNA. According to
its associated gene card [5], it is associated with squamous cell
carcinoma in the head and neck. This is an interesting association, and
not far off from breast cancer, although a stretch for sure.
Looking further into squamous breast cancerous tissues brought me to
this String network.
Figure 17: String Network for squamous carcinoma
in breast tissue. Pulled by using the STITCH disease query on squamous
carcinoma.
Notably, ERBB2 is present in yellow. This is the definition
of expression of HER2, and so its relation to squamous
carcinoma in breast cancerous tissue is very interesting. Additionally,
we see BRCA1, a classic, and MUC1, which was in our aggregate model
design.
Associated Journal
Entry
My associated journal entry wiki link for this assignment is here.
Acknowledgments
This paper makes use of packages knitr [6],
BiocManager [7], GEOquery [8],
kableExtra [9], edgeR [10],
limma [11], ComplexHeatmap [12],
circlize [13], gprofiler2 [14],
GSA [15], rcurl [16],
ggplot2 [17], grid [18],
gridExtra [19], png [20], RCy3
[21], &
httr [22].
Bibliography
1. Wu SZ, Al-Eryani G, Roden DL, Junankar S, Harvey K, Andersson A, et
al. A single-cell and spatially resolved atlas of human breast cancers.
Nature genetics. 2021;53:1334–47.
2. Parker JS, Mullins M, Cheang MC, Leung S, Voduc D, Vickery T, et al.
Supervised risk predictor of breast cancer based on intrinsic subtypes.
Journal of clinical oncology. 2009;27:1160–7.
6. Xie Y.
Dynamic documents with
R and knitr. 2nd edition. Boca Raton, Florida: Chapman;
Hall/CRC; 2015.
10. Chen Y, Lun AT, McCarthy DJ, Chen L, Baldoni P, Ritchie ME, et al.
edgeR: Empirical
analysis of digital gene expression data in r. 2025.
11. Ritchie ME, Phipson B, Wu D, Hu Y, Law CW, Shi W, et al.
limma powers differential expression analyses for
RNA-sequencing and microarray studies. Nucleic Acids
Research. 2015;43:e47.
12. Gu Z. Complex heatmap visualization. iMeta. 2022.
https://doi.org/10.1002/imt2.43.
13. Gu Z, Gu L, Eils R, Schlesner M, Brors B. Circlize implements and
enhances circular visualization in r. Bioinformatics. 2014;30:2811–2.
14. Kolberg L, Raudvere U, Kuzmin I, Vilo J, Peterson H. gprofiler2– an
r package for gene list functional enrichment analysis and namespace
conversion toolset g:profiler. F1000Research. 2020;9 (ELIXIR).
15. Efron B, Tibshirani R.
GSA: Gene set analysis.
2024.
17. Wickham H, Chang W, Henry L, Pedersen TL, Takahashi K, Wilke C, et
al.
ggplot2: Create elegant data
visualisations using the grammar of graphics. 2024.
18. R Core Team.
R: A language and
environment for statistical computing. Vienna, Austria: R Foundation
for Statistical Computing; 2024.
21. Gustavsen, A. J, Pai, Shraddha, Isserlin, Ruth, et al. RCy3: Network
biology using cytoscape from within r. F1000Research. 2019.
https://doi.org/10.12688/f1000research.20887.3.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAzIgpzdWJ0aXRsZTogIkRhdGEgU2V0IFBhdGh3YXkgYW5kIE5ldHdvcmsgQW5hbHlzaXMiCmF1dGhvcjogIkFubmFiZWxsYSBCcmVnYXp6aSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCmJpYmxpb2dyYXBoeTogYTNfcmVmZXJlbmNlcy5iaWIKY3NsOiBiaW9tZWQtY2VudHJhbC5jc2wKbGluay1jaXRhdGlvbnM6IHRydWUKLS0tCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpsaWJyYXJ5KGtuaXRyKQppZiAoIXJlcXVpcmUoIkJpb2NNYW5hZ2VyIiwgcXVpZXRseSA9IFRSVUUpKQogICAgaW5zdGFsbC5wYWNrYWdlcygiQmlvY01hbmFnZXIiKQoKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgiR0VPcXVlcnkiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiR0VPcXVlcnkiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiR0VPcXVlcnkiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgia2FibGVFeHRyYSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJrYWJsZUV4dHJhIil9LCAKICAgICAgICAgZmluYWxseSA9IGxpYnJhcnkoImthYmxlRXh0cmEiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgiZWRnZVIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZWRnZVIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZWRnZVIiKSkKdHJ5Q2F0Y2goZXhwciA9IHsgbGlicmFyeSgibGltbWEiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygibGltbWEiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgibGltbWEiKSkKaWYgKCFyZXF1aXJlKCJDb21wbGV4SGVhdG1hcCIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJDb21wbGV4SGVhdG1hcCIpCmlmICghcmVxdWlyZSgiY2lyY2xpemUiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2lyY2xpemUiKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJncHJvZmlsZXIyIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImdwcm9maWxlcjIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZ3Byb2ZpbGVyMiIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJHU0EiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiR1NBIil9LCAKICAgICAgICAgZmluYWxseSA9IGxpYnJhcnkoIkdTQSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJnZ3Bsb3QyIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiZ2dwbG90MiIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJSQ3VybCIpIH0sCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoIlJDdXJsIil9LAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiUkN1cmwiKSkKCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoIlJDeTMiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIlJDeTMiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiUkN5MyIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJodHRyIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJodHRyIil9LCAKICAgICAgICAgZmluYWxseSA9IGxpYnJhcnkoImh0dHIiKSkKCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShwbmcpCmxpYnJhcnkoZ3JpZEV4dHJhKQoKb3B0aW9ucyhrbml0ci50YWJsZS5mb3JtYXQgPSAiaHRtbCIpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCkJ1bGsgUk5BIHNlcXVlbmNpbmcgZGF0YSBvbiAyNCBwcmUtdHJlYXRtZW50IGJyZWFzdCBjYW5jZXIgdHVtb3VycyBwZXJmb3JtZWQgYnkgV3UgZXQgYWwuIFtAd3UyMDIxc2luZ2xlXSB3YXMgZG93bmxvYWRlZCBmcm9tIGBHRU9gIHdpdGggYWNjZXNzaW9uIFtHU0UxNzYwNzhdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvZ2VvL3F1ZXJ5L2FjYy5jZ2k/YWNjPUdTRTE3NjA3OCksIGFuZCBbYXNzb2NpYXRlZCBwdWJsaWNhdGlvbl0oaHR0cHM6Ly9wbWMubmNiaS5ubG0ubmloLmdvdi9hcnRpY2xlcy9QTUM5MDQ0ODIzLykuCgpgYGB7cn0KZ2VvX2lkIDwtICJHU0UxNzYwNzgiCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KZ3NlIDwtIGdldEdFTyhnZW9faWQsIEdTRU1hdHJpeD1GQUxTRSkKZ3BsIDwtIG5hbWVzKGdzZUBncGxzKQpncGxfaW5mbyA8LSBNZXRhKGdldEdFTyhncGwpKQpgYGAKClRoaXMgZGF0YXNldCB3YXMgc2VxdWVuY2VkIHVzaW5nIGByIGdwbF9pbmZvJHRpdGxlYCwgc3VibWl0dGVkIG9uIGByIGdwbF9pbmZvJHN1Ym1pc3Npb25fZGF0ZWAuCgpCcmVhc3QgY2FuY2VycyBhcmUgY2xpbmljYWxseSBzdHJhdGlmaWVkIGJhc2VkIG9uOgoKLSBleHByZXNzaW9uIG9mIHRoZSBlc3Ryb2dlbiByZWNlcHRvciAoKkVSKiksIAotIGV4cHJlc3Npb24gb2YgdGhlIHByb2dlc3Rlcm9uZSByZWNlcHRvciAoKlBSKiksIGFuZAotIG92ZXJleHByZXNzaW9uIG9mICpIRVIyKiAob3IgYW1wbGlmaWNhdGlvbiBvZiAqSEVSMiogZ2VuZSAqRVJCQjIqKQoKVGhpcyByZXN1bHRzIGluIHRoZSBmb2xsb3dpbmcgdGhyZWUgX19jbGluaWNhbCBzdWJ0eXBlc19fIHdpdGhpbiB0aGlzIGRhdGFzZXQ6CgotIEx1bWluYWwgaWUuIEVSKzsgKCpFUisqLCAqUFIrLy0qKQotIEhFUjIrOyAoKkhFUjIrKiwgKkVSKy8tKiwgKlBSKy8tKikKLSBUcmlwbGUgTmVnYXRpdmUgaWUuIFROQkM7ICgqRVItKiwgKlBSLSosICpIRVIyLSopCgpCcmVhc3QgY2FuY2VycyBhcmUgYWxzbyBzdHJhdGlmaWVkIG9uIGJ1bGsgdHJhbnNjcmlwdG9taWMgcHJvZmlsaW5nIHZpYSBQQU01MCBnZW5lIHNpZ25hdHVyZXMgW0BwYXJrZXIyMDA5c3VwZXJ2aXNlZF0gZGVzY3JpYmluZyBmaXZlIF9fbW9sZWN1bGFyIHN1YnR5cGVzX186IEx1bWluYWwgQSwgTHVtaW5hbCBCLCBIRVIyLWVucmljaGVkLCBCYXNhbC1saWtlLCBhbmQgTm9ybWFsLWxpa2UuCgpUaGUgfjcwLTgwJSBjb25jb3JkYW5jZSBiZXR3ZWVuIGNsaW5pY2FsIGFuZCBtb2xlY3VsYXIgc3VidHlwZXMgbW90aXZhdGVkIHRoaXMgc3R1ZHkgdG8gaW1wcm92ZSBmdW5jdGlvbmFsIHVuZGVyc3RhbmRpbmcgb2YgYnJlYXN0IGNhbmNlciBpbiBhIGJyb2FkZXIgYW5kIG1vcmUgY29oZXJlbnQgc2Vuc2UuCgpGb3IgdGhpcyBzdHVkeSwgdGhlIGNsaW5pY2FsIHN1YnR5cGUgY29uZGl0aW9ucyBjbGFzc2lmaWVkIGFyZSBhcyBmb2xsb3dzOgoKLSBgSEVSMitgIDsgKCpIRVIyKyosICpFUi0qLCAqUFIrLy0qKQotIGBIRVIyKy9FUitgIDsgKCpIRVIyKyosICpFUisqLCAqUFIrLy0qKQotIGBFUitgIDsgKCpIRVIyLSosICpFUisqLCAqUFIrLy0qKQotIGBUTkJDYCA7ICgqSEVSMi0qLCAqRVItKiwgKlBSLSopCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0Kbm9ybWFsaXplZF9jb3VudHMgPC0gcmVhZC50YWJsZSgKICBmaWxlPWZpbGUucGF0aChnZXR3ZCgpLCBnZW9faWQsCiAgICAgICAgICAgICAgICAgcGFzdGUoZ2VvX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAibm9ybWFsaXplZF9jb3VudHMudHh0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgc2VwPSJfIikpLAogIGhlYWRlcj1UUlVFLCBzZXA9Ilx0IiwgCiAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwgCiAgY2hlY2submFtZXM9RkFMU0UpCmBgYAoKVGhlIGRpc3RyaWJ1dGlvbiBvZiBjbGluaWNhbCBzdWJ0eXBlcyBhY3Jvc3MgdGhlIDI0IHNhbXBsZXMgaXMgc2hvd24gaW4gdGFibGUgMS4KCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CnR5cGVzIDwtIGRvLmNhbGwocmJpbmQsCiAgICAgICAgICAgICAgICAgbGFwcGx5KGdzZUBnc21zLCwKICAgICAgICAgICAgICAgICAgICAgICAgRlVOPWZ1bmN0aW9uKHgsIC4uLil7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYyh4QGhlYWRlciR0aXRsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhAaGVhZGVyJGNoYXJhY3RlcmlzdGljc19jaDEpfSkpWyxjKDEsMildCnR5cGVzWywyXSA8LSBnc3ViKHR5cGVzWywyXSwKICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJjbGluaWNhbF9zdWJ0eXBlOiAiLAogICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKQoKcHJlc2VudCA8LSBjb2xuYW1lcyhub3JtYWxpemVkX2NvdW50cykKdHlwZXMgPC0gdHlwZXNbd2hpY2godHlwZXNbLDFdICVpbiUgcHJlc2VudCksXQoKdHlwZXMgPC0gY2JpbmQodHlwZXMsIGdyZXBsKCJeW0hdW0VdW1JdWzJdWytdIiwgdHlwZXNbLDJdKSkKdHlwZXMgPC0gY2JpbmQodHlwZXMsIGdyZXBsKCJbRV1bUl1bK10kIiwgdHlwZXNbLDJdKSkKY29sbmFtZXModHlwZXMpIDwtIGMoInNhbXBsZSIsICJzdWJ0eXBlIiwgImhlcjIiLCAiZXIiKQp0eXBlc19kZiA8LSBhcy5kYXRhLmZyYW1lKHR5cGVzKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmhlcjIgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIkhFUjIrIikpCmhlcjJlciA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiSEVSMisvRVIrIikpCnRuYmMgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIlROQkMiKSkKZXIgPSBsZW5ndGgod2hpY2godHlwZXNbLCJzdWJ0eXBlIl0gPT0gIkVSKyIpKQp0b3RhbCA9IHN1bShoZXIyLCBoZXIyZXIsIHRuYmMsIGVyKQoKc3VidHlwZV9jb3VudHMgPSBkYXRhLmZyYW1lKGMoaGVyMiwgaGVyMmVyLCB0bmJjLCBlciwgdG90YWwpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gYygiSEVSMisiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhFUjIrL0VSKyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVE5CQyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRVIrIiwgIlRvdGFsIikpCnN1YnR5cGVfY291bnRzJHBlcmNlbnRhZ2VzID0gc3VidHlwZV9jb3VudHNbLDFdICogMTAwIC8gdG90YWwKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CnN1YnR5cGVfY291bnRzICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxOiBDbGluaWNhbCBicmVhc3QgY2FuY2VyIHN1YnR5cGUgc3BsaXRzIGluIG91ciBkYXRhc2V0IiwgCiAgICAgIGRpZ2l0cz0yLAogICAgICBjb2wubmFtZXM9YygiQ291bnQiLCAiUGVyY2VudCIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkgJT4lCiAgcm93X3NwZWMoNSwgYm9sZCA9IFQpCmBgYAoKVGhpcyBsZWFkcyB0byAKCiogYHIgNDAwLzI0YCUgb2Ygc2FtcGxlcyBjb250YWluaW5nIGBIRVIyYCBleHByZXNzaW9uLCBhbmQgCiogYHIgMTQwMC8yNGAlIG9mIHNhbXBsZXMgY29udGFpbmluZyBgRVJgIGV4cHJlc3Npb24sIAoKV2l0aCB0aGUgb3ZlcmxhcHMgZ2l2aW5nIHVzIAoKKiBgciAyMDAvNGAlIG9mIHRob3NlIHdpdGggYEhFUjJgIGV4cHJlc3NlZCBhbHNvIGhhZCBgRVJgIGV4cHJlc3NlZCwgCiogYHIgMjAwLzE0YCUgb2YgdGhvc2Ugd2l0aCBgRVJgIGV4cHJlc3NlZCBhbHNvIGhhZCBgSEVSMmAgZXhwcmVzc2VkLgoKClRoZSByYXcgY291bnRzIHdlcmUgY2xlYW5lZCwgbWFwcGVkIHRvIFtIVUdPIEdlbmUgTm9tZW5jbGF0dXJlIENvbW1pdHRlZSAoSEdOQykgU3ltYm9sc10oaHR0cHM6Ly93d3cuZ2VuZW5hbWVzLm9yZy8pLCBhbmQgbm9ybWFsaXplZCB0byBwcm9kdWNlIGZpbmFsIGNvdW50cy4gT2YgdGhlIG9yaWdpbmFsIGA1ODM4N2AgZ2VuZXMsIHdlIHdlcmUgYWJsZSB0byBtYXAgYW5kIHByb2R1Y2UgYDI4NzEyYCB1bnZlcnNpb25lZCwgdW5pcXVlIGdlbmVzLCBvZiB3aGljaCBmaWx0ZXJpbmcgb3V0bGllcnMgKGtlZXBpbmcgZ2VuZXMgcHJlc2VudCBpbiBhIG1pbmltdW0gb2YgYDEyYCBzYW1wbGVzKSByZXN1bHRlZCBpbiBgMTQ4MDBgIGdlbmVzIHJlbWFpbmluZy4gCgpUaGUgZGVuc2l0eSBwbG90IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGNsZWFuZWQsIGZpbHRlcmVkLCBhbmQgbm9ybWFsaXplZCBjb3VudHMgcGVyIG1pbGxpb24gYWNyb3NzIGFsbCBzYW1wbGVzICh2YXJ5aW5nIGNvbG91cnMpLiAKCjxici8+CgohW0ZpZ3VyZSAxOiBTbW9vdGhpbmcgZGVuc2l0eSBvZiBmaWx0ZXJlZCBhbmQgbm9ybWFsaXplZCBDUE0gY291bnRzIGZvciAyNCBzYW1wbGVzIGFjcm9zcyBmb3VyIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIgdGlzc3VlLiBDb3VudHMgd2VyZSBmaWx0ZXJlZCB3aXRoIGBlZGdlUmAncyBgY3BtKClgIHRocmVzaG9sZGVkIGF0IGEgbWluaW11bSBzdW0gb2YgMTIgQ1BNIGFjcm9zcyBzYW1wbGVzIGZvciBlYWNoIGdlbmUuIENvdW50cyB3ZXJlIG5vcm1hbGl6ZWQgd2l0aCBgZWRnZVJgJ3MgYERHRUxpc3QoKWAgYWNyb3NzIGFsbCBmb3VyIGNsaW5pY2FsIHN1YnR5cGVzLiBOb3JtYWxpemF0aW9uIGZhY3RvcnMgd2VyZSBjYWxjdWxhdGVkIHZpYSBUTU0uIF0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL0dTRTE3NjA3OF9maWx0X25vcm1fZGVuc2l0eS5wbmcpCgoKPGJyLz4KRGlzcGVyc2lvbiB3YXMgY2FsY3VsYXRlZCB1c2luZyBgZWRnZVJgIHRvIGRlc2NyaWJlIGRldmlhdGlvbiBvZiB2YXJpYW5jZSBmcm9tIHRoZSBtZWFuLiBUaGUgQmlvbG9naWNhbCBDb2VmZmljaWVudCBvZiBWYXJpYXRpb24gKEJDVikgaXMgZGlzcGVyc2lvbi1zcXVhcmVkLCBhbmQgcmVwcmVzZW50cyB0aGUgbWVhbi12YXJpYW5jZSByZWxhdGlvbnNoaXAgYW1vbmcgZ2VuZXMuCgohW0ZpZ3VyZSAyOiBCaW9sb2dpY2FsIENvZWZmaWNpZW50IG9mIFZhcmlhdGlvbiAoRGlzcGVyc2lvbiBzcXVhcmVkKSBmb3IgMjQgc2FtcGxlcyBhY3Jvc3MgZm91ciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIHRpc3N1ZSBnZW5lLXdpc2UuIERpc3BlcnNpb24gd2FzIGNhbGN1bGF0ZWQgdXNpbmcgYGVkZ2VSYCdzIGBwbG90QkNWKClgIG9uIHRoZSBtb2RlbCBkZXNpZ25lZCBhY3Jvc3MgYWxsIGZvdXIgY2xpbmljYWwgc3VidHlwZXMuXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvR1NFMTc2MDc4X2Jjdi5wbmcpCgo8YnIvPgpUaGUgbm9ybWFsaXplZCBjb3VudHMgd2VyZSBtb2RlbGVkIGJ5IHR3byBkZXNpZ25zLiBUaGUgZmlyc3QgYmVpbmcgYW4gYWdncmVnYXRlIGRlc2lnbiBjb25zaWRlcmluZyBhbGwgY2xpbmljYWwgc3VidHlwZXMgYXMgZGlzdGluY3QsIGllLiAqSEVSMisvRVIrKiwgKkhFUjIrKiwgKkVSKyosIGFuZCAqVE5CQyouIFRoZSBzZWNvbmQgYmVpbmcgYSBzcGxpdCBiaW5hcnktcGFpcmluZyBtb2RlbCBjb21iaW5pbmcgdGhlIHR3byBzZXBhcmF0ZSBjbGFzc2lmaWNhdGlvbiBzdWJ0eXBlcywgaWUuICpIRVIyKy8tKiBhbmQgKkVSKy8tKiBhcyBhIGJpbmFyeSBwYWlyLiBUaGUgc2VwYXJhdGUgbW9kZWwgZGVzaWducyByZXByZXNlbnRlZCBkaWZmZXJlbnQgcGVyc3BlY3RpdmVzIG9uIGxhYmVsaW5nIHRoZSBkYXRhIGFuZCBhbGxvdyBmb3IgbW9yZSBzcGVjaWZpYyBvciBnZW5lcmljIGNvbmNsdXNpb25zLgoKYGBge3J9CiMgYWdncmVnYXRlIG1vZGVsIGRlc2lnbgptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gdHlwZXNfZGYkc3VidHlwZSkKCiMgc3BsaXQgbW9kZWwgZGVzaWduIChiaW5hcnkgcGFpcnMpCnNwbHRfbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHR5cGVzX2RmJGhlcjIgKyB0eXBlc19kZiRlcikKYGBgCgpUaGUgYFF1YXNpLUxpa2VsaWhvb2QgTW9kZWxgIGZyb20gYGVkZ2VSYCB3YXMgdXNlZCB0byBwcm9kdWNlIGBRdWFzaS1MaWtlbGlob29kIEZpdHNgIGZvciBlYWNoIG1vZGVsIGRlc2lnbiwgYXQgd2hpY2ggcG9pbnQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gd2FzIGNhbGN1bGF0ZWQgYWNyb3NzIHRoZSBtb2RlbHMuCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZSd9Cm5vcm1fbWF0cml4IDwtIGFzLm1hdHJpeChub3JtYWxpemVkX2NvdW50cykKYGBgCgpgYGB7cn0KIyBub3JtYWxpemVkIGNvdW50cyBncm91cGVkIGJ5IGNsaW5pY2FsIHN1YnR5cGUKZCA8LSBER0VMaXN0KGNvdW50cz1ub3JtX21hdHJpeCwgCiAgICAgICAgICAgICBncm91cD10eXBlc19kZiRzdWJ0eXBlKQoKIyBlc3RpbWF0ZSBkaXNwZXJzaW9uIG9uIHN1YnR5cGUgbW9kZWwgZGVzaWduCmRfIDwtIGVzdGltYXRlRGlzcChkLCBtb2RlbF9kZXNpZ24pCnFsZml0IDwtIGdsbVFMRml0KGRfLCBtb2RlbF9kZXNpZ24pCgojIGluIHBhcmFsbGVsLCBlc3RpbWF0ZSBkaXNwZXJzaW9uIG9uIGJpbmFyeSBwYWlyaW5nIG1vZGVsIGRlc2lnbgpkX3NwbHQgPC0gZXN0aW1hdGVEaXNwKGQsIHNwbHRfbW9kZWxfZGVzaWduKQpxbGZpdF9zcGx0IDwtIGdsbVFMRml0KGRfc3BsdCwgc3BsdF9tb2RlbF9kZXNpZ24pCgojIGZpdCBzdWJ0eXBlIG1vZGVsIGRlc2lnbgpxbGYuc3VidHlwZXMgPC0gZ2xtUUxGVGVzdChxbGZpdCkKCiMgZml0IHNwbGl0IG1vZGVsIGRlc2lnbgpxbGYuaGVyMnAgPC0gZ2xtUUxGVGVzdChxbGZpdF9zcGx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgY29lZj0ndHlwZXNfZGYkZXJUUlVFJykKcWxmLmVycCA8LSBnbG1RTEZUZXN0KHFsZml0X3NwbHQsIAogICAgICAgICAgICAgICAgICAgICAgY29lZj0ndHlwZXNfZGYkaGVyMlRSVUUnKQpgYGAKClRoZSBfX0JlbmphbWluaS1Ib2NoYmVyZ19fIG1ldGhvZCBmb3IgZmFsc2UgZGlzY292ZXJ5IHdhcyB1c2VkIHRvIGNvcnJlY3QgcC12YWx1ZXMgdG8gY2xhc3NpZnkgdGhlIHJlc3VsdGluZyBnZW5lcyB0aGF0IHBhc3NlZCBjb3JyZWN0aW9uIGZvciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBpbiB0aGVpciByZXNwZWN0aXZlIG1vZGVscywgcHJvZHVjaW5nIHRoZSBmb2xsb3dpbmcgdm9sY2FubyBwbG90cy4gTm90ZSB0aGF0IG9ubHkgdGhlIGFnZ3JlZ2F0ZSBkZXNpZ24gYW5kICpFUiogc3BlY2lmaWMgZXhwcmVzc2lvbiBtb2RlbHMgYXJlIHNob3duIHNpbmNlIG5vIGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uIGZvciB0aGUgKkhFUjIqIHNwZWNpZmljIGRlc2lnbi4KPGJyLz4KCiFbRmlndXJlIDM6IFZvbGNhbm8gUGxvdCBmb3Igc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgaW4gMjQgc2FtcGxlcyBhY3Jvc3MgZm91ciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIHRpc3N1ZSAoYWdncmVnYXRlIGRlc2lnbikuIERpZmZlcmVudGlhbCBleHByZXNzaW9uIHdhcyBjYWxjdWxhdGVkIGFjcm9zcyB0aGUgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiBhY3Jvc3MgYWxsIGZvdXIgY2xpbmljYWwgc3VidHlwZXMuIFNpZ25pZmljYW50IGJlZm9yZSBjb3JyZWN0aW9uIGlzIHJlcHJlc2VudGVkIGJ5IHAgPCAwLjA1LCB3aXRoIHNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24gYmVpbmcgRkRSIDwgMC4wNS5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy92b2xjYW5vX2FnZ3JlZ2F0ZS5wbmcpCgo8YnIvPgoKVGhlIGFnZ3JlZ2F0ZSBtb2RlbCBoaWdobGlnaHRzIGluIHJlZCAqQ0QyMDcqLCAqTUtYKiwgYW5kICpBTlhBOCogYXMgZ2VuZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYWZ0ZXIgY29ycmVjdGlvbiBmb3IgZmFsc2UgZGlzY292ZXJ5LgoKIVtGaWd1cmUgNDogVm9sY2FubyBQbG90IGZvciBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBpbiAyNCBzYW1wbGVzIGFjcm9zcyBiaW5hcnkgb3Zlci1leHByZXNzaW9uIG9mIEVSIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIgdGlzc3VlIChzcGxpdCBkZXNpZ24pLiBEaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiB3YXMgY2FsY3VsYXRlZCBhY3Jvc3MgRVIgZXhwcmVzc2lvbiBkZXNpZ24uIFNpZ25pZmljYW50IGJlZm9yZSBjb3JyZWN0aW9uIGlzIHJlcHJlc2VudGVkIGJ5IHAgPCAwLjA1LCB3aXRoIHNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24gYmVpbmcgRkRSIDwgMC4wNS5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy92b2xjYW5vX2VyLnBuZykKCjxici8+CgpUaGUgc3BsaXQgbW9kZWwgaW4gdGVybXMgb2YgKkVSKiBvdmVyLWV4cHJlc3Npb24gaGlnaGxpZ2h0cyBpbiByZWQgKkVQSEEzKiwgKktDTk1CMiosICpDTEVDMUIqLCAqQ1lQMkcxUCosICpDREgyNiosICpDQVNDMyosICpURkYzKiwgKlJBUEdFRkwxKiwgKk1TTDEqLCAqTVVDNCosIGFuZCAqVEhSQSogYXMgZ2VuZXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYWZ0ZXIgY29ycmVjdGlvbiBmb3IgZmFsc2UgZGlzY292ZXJ5LgoKVXNpbmcgdGhlc2UgbW9kZWxzLCBub24tdGhyZXNob2xkZWQgZ2VuZS1zZXRzIGNhbiBiZSBwdWxsZWQgYnkgcmFua2luZyBhY2NvcmRpbmcgdG8gLWxvZyhwLXZhbHVlcykgYW5kIHNpZ25pbmcgYWNjb3JkaW5nIHRvIHRoZSBsb2cgZm9sZC1jaGFuZ2UuCgpgYGB7cn0KIyBjcmVhdGUgbm9uLXRocmVzaG9sZGVkIGdlbmUgc2V0cwoKIyBhY3Jvc3MgYWxsIGNsaW5pY2FsIHN1YnR5cGVzCm50X2dlbmVzZXQgPC0gcWxmLnN1YnR5cGVzJHRhYmxlCm50X2dlbmVzZXRbLCJSYW5rIl0gPC0gLWxvZzEwKG50X2dlbmVzZXQkUFZhbHVlKSAqIHNpZ24obnRfZ2VuZXNldCRsb2dGQykKbnRfZ2VuZXNldCA8LSBudF9nZW5lc2V0W29yZGVyKG50X2dlbmVzZXQkUmFuaywgZGVjcmVhc2luZz1UUlVFKSxdCgojIGFjcm9zcyBFUiBvdmVyLWV4cHJlc3Npb24KZXJfZ2VuZXNldCA8LSBxbGYuZXJwJHRhYmxlCmVyX2dlbmVzZXRbLCJSYW5rIl0gPC0gLWxvZzEwKGVyX2dlbmVzZXQkUFZhbHVlKSAqIHNpZ24oZXJfZ2VuZXNldCRsb2dGQykKZXJfZ2VuZXNldCA8LSBlcl9nZW5lc2V0W29yZGVyKGVyX2dlbmVzZXQkUmFuaywgZGVjcmVhc2luZz1UUlVFKSxdCmBgYAoKVGhlIHJhbmtlZCBnZW5lLXNldHMgYXJlIHNhdmVkIGFzIGAucm5rYCBmaWxlcyBmb3IgZnVydGhlciBhbmFseXNpcyBpbiB0aGUgcmVtYWluZGVyIG9mIHRoaXMgcmVwb3J0LgoKYGBge3J9CiMgZm9yIHRoZSBhZ2dyZWdhdGUgY2xpbmljYWwgc3VidHlwZSBtb2RlbAojIGNyZWF0ZSBhIHNlcGFyYXRlIHJhbmtzIG1hdHJpeCB3aXRoIG9ubHkgZ2VuZSBuYW1lIGFuZCByYW5rCmdlbmVzZXRfcmFua3MgPC0gY2JpbmQocm93bmFtZXMobnRfZ2VuZXNldCksIG50X2dlbmVzZXRbLCJSYW5rIl0pCmNvbG5hbWVzKGdlbmVzZXRfcmFua3MpIDwtIGMoIkdlbmVOYW1lIiwgIlJhbmsiKQoKcmFua2VkX2dlbmVzZXRfZmlsZXBhdGggPC0gZmlsZS5wYXRoKGdldHdkKCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhZ19yYW5rcy5ybmsiKQojIGlmIHRoZSBmaWxlIGRvZXMgbm90IGV4aXN0IGFscmVhZHkKaWYgKCFmaWxlLmV4aXN0cyhyYW5rZWRfZ2VuZXNldF9maWxlcGF0aCkpIHsKICAjIHdyaXRlIHRoaXMgbWF0cml4IHRvIHRoZSBmaWxlCiAgd3JpdGUudGFibGUoZ2VuZXNldF9yYW5rcywKICAgICAgICAgICAgICByYW5rZWRfZ2VuZXNldF9maWxlcGF0aCwKICAgICAgICAgICAgICBxdW90ZT1GQUxTRSxzZXA9Ilx0Iixyb3cubmFtZT1GQUxTRSkKfQoKIyBmb3IgdGhlIEVSIG92ZXItZXhwcmVzc2lvbiBtb2RlbAojIGNyZWF0ZSBhIHNlcGFyYXRlIHJhbmtzIG1hdHJpeCB3aXRoIG9ubHkgZ2VuZSBuYW1lIGFuZCByYW5rCmdlbmVzZXRfZXJfcmFua3MgPC0gY2JpbmQocm93bmFtZXMoZXJfZ2VuZXNldCksIGVyX2dlbmVzZXRbLCJSYW5rIl0pCmNvbG5hbWVzKGdlbmVzZXRfZXJfcmFua3MpIDwtIGMoIkdlbmVOYW1lIiwgIlJhbmsiKQoKcmFua2VkX2VyX2dlbmVzZXRfZmlsZXBhdGggPC0gZmlsZS5wYXRoKGdldHdkKCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJlcl9yYW5rcy5ybmsiKQojIGlmIHRoZSBmaWxlIGRvZXMgbm90IGV4aXN0IGFscmVhZHkKaWYgKCFmaWxlLmV4aXN0cyhyYW5rZWRfZXJfZ2VuZXNldF9maWxlcGF0aCkpIHsKICAjIHdyaXRlIHRoaXMgbWF0cml4IHRvIHRoZSBmaWxlCiAgd3JpdGUudGFibGUoZ2VuZXNldF9lcl9yYW5rcywKICAgICAgICAgICAgICByYW5rZWRfZXJfZ2VuZXNldF9maWxlcGF0aCwKICAgICAgICAgICAgICBxdW90ZT1GQUxTRSxzZXA9Ilx0Iixyb3cubmFtZT1GQUxTRSkKfQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KaGVhZChnZW5lc2V0X3JhbmtzKSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMjogR2VuZSBSYW5rcyBmb3IgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiBhY3Jvc3MgSEVSMisvRVIrLCBIRVIyKywgRVIrLCBhbmQgVE5CQyBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyLiIsIGRpZ2l0cz00KSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CmhlYWQoZ2VuZXNldF9lcl9yYW5rcykgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDM6IEdlbmUgUmFua3MgZm9yIHNwbGl0IG1vZGVsIGRlc2lnbiBhY3Jvc3MgRVIgKy8tIG92ZXJleHByZXNzaW9uIGFzIGEgY2xpbmljYWwgc3VidHlwZSBjbGFzc2lmaWVyIG9mIGJyZWFzdCBjYW5jZXIuIiwgZGlnaXRzPTQpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKClRoZSBmaXJzdCBmaXZlIGdlbmVzIGFyZSBkaXNwbGF5ZWQgaW4gdGhlIHRhYmxlcyBhYm92ZSBmb3IgdGhlIHR3byBtb2RlbCBkZXNpZ25zIG9mIGludGVyZXN0LgoKIyBOb24tVGhyZXNob2xkZWQgR2VuZS1TZXQgRW5yaWNobWVudCBBbmFseXNpcwoKVXNpbmcgdGhlIEdTRUEgY29tbWFuZC1saW5lIGludGVyZmFjZSBgLmphcmAgZm9yIGNvbXBhdGliaWxpdHkgb2YgdXNpbmcgR1NFQSB3aXRoIFIsIHdlIGNhbiBkb3dubG9hZCB0aGUgZGVzaXJlZCBnZW5lLXNldCBmaWxlIGZyb20gdGhlIEJhZGVyIExhYi4KClRoZSBjb2RlIGJlbG93IGlzIGFkYXB0ZWQgZnJvbSBSdXRoIElzc2VybGluIFtAcmlzc2VybGluXS4KCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KIyB2YXJpYWJsZSBuYW1lcyBmb3IgZWFzaWVyIG1vZGlmaWNhdGlvbgpnc2VhX2phciA9ICJ+L0dTRUFfNC4zLjIvZ3NlYS1jbGkuc2giCndvcmtpbmdfZGlyID0gIn4vcHJvamVjdHMvR1NFMTc2MDc4IgpvdXRwdXRfZGlyID0gIn4vcHJvamVjdHMvR1NFMTc2MDc4L2dzZWEiCmFuYWx5c2lzX25hbWVfYWcgPSAiY2xpbmljYWwgc3VidHlwZXMiCmFuYWx5c2lzX25hbWVfZXIgPSAiRVIgb3Zlci1leHByZXNzaW9uIgphZ19ybmtfZmlsZSA9ICJhZ19yYW5rcy5ybmsiCmVyX3Jua19maWxlID0gImVyX3JhbmtzLnJuayIKCiMgdGhlIE1hcmNoIDFzdCByZWxlYXNlIChsYXRlc3QgYXQgdGhpcyBwb2ludCkKZ210X3VybCA9ICJodHRwOi8vZG93bmxvYWQuYmFkZXJsYWIub3JnL0VNX0dlbmVzZXRzL01hcmNoXzAxXzIwMjUvSHVtYW4vc3ltYm9sLyIKCiN1c2UgdGhlIG5vbi1maWx0ZXJlZCBnbXQKZ210X2ZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aCA9IG91dHB1dF9kaXIsIHBhdHRlcm4gPSAiXFwuZ210IikKaWYgKGxlbmd0aChnbXRfZmlsZXMpID09IDApIHsKICAjIGRvd25sb2FkIHRoZSBkZXNpcmVkIGdlbmUtc2V0IGZpbGUKICBmaWxlbmFtZXMgPSBnZXRVUkwoZ210X3VybCkKICB0YyA9IHRleHRDb25uZWN0aW9uKGZpbGVuYW1lcykKICBjb250ZW50cyA9IHJlYWRMaW5lcyh0YykKICBjbG9zZSh0YykKICAgIAogICMgZmlsdGVyIGJhc2VkIG9uIHRoZSBmb2xsb3dpbmcgc3BlY2lmaWNhdGlvbnM6CiAgIyArIEdlbmUgT250b2xvZ3kgOiBCaW9sb2dpY2FsIFByb2Nlc3NlcyB0ZXJtcywgCiAgIyAgICsgaW5jbHVkZSBBbGwgUGF0aHdheXMKICAjIC0gV2lraVBhdGh3YXlzIChQRk9DUiksIGFuZAogICMgLSBHTyBJRUEgKGVsZWN0cm9uaWMgYW5ub3RhdGlvbnMpCiAgcnggPSBncmVnZXhwcigiKD88PTxhIGhyZWY9XCIpKC4qLkdPQlBfQWxsUGF0aHdheXNfbm9QRk9DUl9ub19HT19pZWEuKi4pKC5nbXQpKD89XCI+KSIsCiAgICAgICAgICAgICAgICAgIGNvbnRlbnRzLCBwZXJsID0gVFJVRSkKICBnbXRfZmlsZSA9IHVubGlzdChyZWdtYXRjaGVzKGNvbnRlbnRzLCByeCkpCiAgCiAgZGVzdF9nbXRfZmlsZSA8LSBmaWxlLnBhdGgob3V0cHV0X2RpciwgZ210X2ZpbGUpCiAgICAKICAjIGlmIHRoZSBnbXQgZmlsZSBoYXMgbm90IGFscmVhZHkgYmVlbiBkb3dubG9hZGVkCiAgaWYoIWZpbGUuZXhpc3RzKGRlc3RfZ210X2ZpbGUpKXsKICAgICMgZG93bmxvYWQgdGhlIHNwZWNpZmllZCByZWxlYXNlIGZyb20gdGhlIFVSTAogICAgZG93bmxvYWQuZmlsZSgKICAgICAgcGFzdGUoZ210X3VybCxnbXRfZmlsZSxzZXA9IiIpLAogICAgICBkZXN0ZmlsZT1kZXN0X2dtdF9maWxlCiAgICApCiAgfSBlbHNlIHsKICAgIGRlc3RfZ210X2ZpbGUgPC0gZ210X2ZpbGVzWzFdCiAgfQp9CmBgYAoKYGBge3IsIHJlc3VsdHM9J2hpZGUnfQojIGdlbmVyYXRlIHRoZSBjb21tYW5kIGZvciB0aGUgYWdncmVnYXRlIGNsaW5pY2FsIHN1YnR5cGUgbW9kZWwKY21kIDwtIHBhc3RlKCIiLCBnc2VhX2phciwKICAgICAgICAgICAgICJHU0VBUHJlUmFua2VkIC1nbXgiLCBkZXN0X2dtdF9maWxlLAogICAgICAgICAgICAgIi1ybmsiICxmaWxlLnBhdGgod29ya2luZ19kaXIsIGFnX3Jua19maWxlKSwgCiAgICAgICAgICAgICAiLWNvbGxhcHNlIGZhbHNlIC1ucGVybSAxMDAwIC1zY29yaW5nX3NjaGVtZSB3ZWlnaHRlZCIsIAogICAgICAgICAgICAgIi1ycHRfbGFiZWwgIiwgYW5hbHlzaXNfbmFtZV9hZywKICAgICAgICAgICAgICIgIC1wbG90X3RvcF94IDIwIC1ybmRfc2VlZCAxMjM0NSAgLXNldF9tYXggMjAwIiwgIAogICAgICAgICAgICAgIiAtc2V0X21pbiAxNSAtemlwX3JlcG9ydCBmYWxzZSAiLAogICAgICAgICAgICAgIiAtb3V0Iiwgb3V0cHV0X2RpciwgCiAgICAgICAgICAgICAiID4gZ3NlYV9vdXRwdXRfYWcudHh0Iiwgc2VwPSIgIikKIyBpZiB0aGUgb3V0cHV0IGZvbGRlciBkb2VzIG5vdCBhbHJlYWR5IGV4aXN0CmlmIChsZW5ndGgobGlzdC5maWxlcyhwYXRoPW91dHB1dF9kaXIsCiAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuPSJeY2xpbmljYWwuR3NlYVByZXJhbmtlZCIpKSA9PSAwKSB7CiAgc3lzdGVtKGNtZCkgIyBydW4gdGhlIGNtZAp9CgojIGFuZCBnZW5lcmF0ZSB0aGUgY29tbWFuZCBmb3IgdGhlIEVSIG92ZXItZXhwcmVzc2lvbiBjbGFzc2lmaWVyIG1vZGVsCmNtZCA8LSBwYXN0ZSgiIiwgZ3NlYV9qYXIsCiAgICAgICAgICAgICAiR1NFQVByZVJhbmtlZCAtZ214IiwgZGVzdF9nbXRfZmlsZSwKICAgICAgICAgICAgICItcm5rIiAsZmlsZS5wYXRoKHdvcmtpbmdfZGlyLCBlcl9ybmtfZmlsZSksIAogICAgICAgICAgICAgIi1jb2xsYXBzZSBmYWxzZSAtbnBlcm0gMTAwMCAtc2NvcmluZ19zY2hlbWUgd2VpZ2h0ZWQiLCAKICAgICAgICAgICAgICItcnB0X2xhYmVsICIsIGFuYWx5c2lzX25hbWVfZXIsCiAgICAgICAgICAgICAiICAtcGxvdF90b3BfeCAyMCAtcm5kX3NlZWQgMTIzNDUgIC1zZXRfbWF4IDIwMCIsICAKICAgICAgICAgICAgICIgLXNldF9taW4gMTUgLXppcF9yZXBvcnQgZmFsc2UgIiwKICAgICAgICAgICAgICIgLW91dCIsIG91dHB1dF9kaXIsIAogICAgICAgICAgICAgIiA+IGdzZWFfb3V0cHV0X2VyLnR4dCIsIHNlcD0iICIpCiMgaWYgdGhlIG91dHB1dCBmb2xkZXIgZG9lcyBub3QgYWxyZWFkeSBleGlzdAppZiAobGVuZ3RoKGxpc3QuZmlsZXMocGF0aD1vdXRwdXRfZGlyLAogICAgICAgICAgICAgICAgICAgICAgcGF0dGVybj0iXkVSLkdzZWFQcmVyYW5rZWQiKSkgPT0gMCkgewogIHN5c3RlbShjbWQpICMgcnVuIHRoZSBjbWQKfQpgYGAKCiMjIFdoYXQgbWV0aG9kIGRpZCB5b3UgdXNlPwoKSSBjaG9zZSB0byB1c2UgYEdTRUFgJ3MgUHJlUmFua2VkIEFuYWx5c2lzIHNpbmNlIEkgaGFkIGZhbWlsaWFyaXR5IHdpdGggaXQgdGhyb3VnaCBteSBqb3VybmFsIGVudHJ5IGFuZCBmb3VuZCBpdCB0byBiZSB2ZXJ5IGluZm9ybWF0aXZlIG9uIGNvbXBsZXRpb24gb2YgdGhlIGFuYWx5c2lzLiBJdCB3YXMgYWxzbyBmbGV4aWJsZSBpbiB0ZXJtcyBvZiB1c2luZyB3aGljaGV2ZXIgZ2VuZSBtYXRyaXggdHJhbnNwb3NlZCBnZW5lLXNldCBmaWxlIEkgd2FudGVkLCB3aGljaCBtZWFudCBJIGNvdWxkIHJlZG8gdGhlIGFuYWx5c2lzIHByb2dyYW1tYXRpY2FsbHkgaWYgSSBuZWVkZWQgdG8gdHJ5IGFnYWluIHdpdGggYSBkaWZmZXJlbnQgb3IgdXBkYXRlZCBnZW5lLXNldC4KCiMjIyBXaGF0IGdlbmUtc2V0cyBkaWQgeW91IHVzZT8gKFNwZWNpZnkgdmVyc2lvbnMgYW5kIGNpdGUgeW91ciBtZXRob2RzKQoKSSBjaG9zZSB0byB1c2UgdGhlIHRoZSBgSHVtYW5gIGdlbmUtc2V0IGZyb20gdGhlIFtCYWRlckxhYl0oaHR0cHM6Ly9kb3dubG9hZC5iYWRlcmxhYi5vcmcvRU1fR2VuZXNldHMvKSByZWxlYXNlZCBvbiBgTWFyY2ggMXN0LCAyMDI1YC4gVGhlIGdlbmUtc2V0cyB3ZXJlIGRldmVsb3BlZCB1c2luZyB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgR08gSHVtYW4gYW5ub3RhdGlvbnMgb24gRGVjZW1iZXIgMjEsIDIwMjUsIHdoaWNoIG1lYW5zIHdlIGFyZSB1c2luZyB0aGUgcmVsZWFzZSBkYXRlZCBtb3N0IHJlY2VudGx5IGJlZm9yZSB0aGlzLiBBcyBzdWNoLCBpdCBpbmNsdWRlcwoKKiBgR086QlBgIDogYEdlbmUgT250b2xvZ3k6IEJpb2xvZ2ljYWwgUHJvY2Vzc2VzYCA7IAogICAgdmVyc2lvbiBfXzIyNV9fIHJlbGVhc2VkIF9fMjQgT2N0b2JlciwgMjAyNF9fCgpUaGVyZSBpcyBhbiBvcHRpb24gdG8gaW5jbHVkZSBgUEZPQ1JgLCB3aGljaCBpcyBgV2lraVBhdGh3YXlzYCwgaG93ZXZlciBJIGRpZCBub3QgaW5jbHVkZSB0aGlzIHNpbmNlIEkgcGVyZm9ybWVkIHRoZSBhbmFseXNpcyBvbmx5IHVzaW5nIGBHTzpCUGAgZmlyc3QgYW5kIGZvdW5kIGl0IHRvIGJlIHN1ZmZpY2llbnQgZm9yIG15IG5lZWRzIGluIHRlcm1zIG9mIHRoaXMgYW5hbHlzaXMuCgojIyBTdW1tYXJpemUgeW91ciBlbnJpY2htZW50IHJlc3VsdHMKClRoZXJlIGFyZSBhIGxvdCBvZiBpbmRpdmlkdWFsIHBsb3RzIGF2YWlsYWJsZSBmb3Igc3BlY2lmaWMgdGVybXMuCgpGaXJzdCwgdGhlIGZvbGxvd2luZyBwbG90cyBhZ3JlZSB3aXRoIG91ciB2b2xjYW5vIHBsb3RzIHRvIGdpdmUgdXMgbW9yZSBjb25maWRlbmNlIGluIHRoZSByZW1haW5pbmcgcmVzdWx0cy4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgbWVzc2FnZT1GQUxTRX0KIyBzaWRlLWJ5LXNpZGUgcGxvdHRpbmcgZnVuY3Rpb24KcGxvdF9ib3RoIDwtIGZ1bmN0aW9uKGltZzEsIGltZzIsIHRleHQpIHsKICBpbWcxIDwtIGdyaWQ6OnJhc3Rlckdyb2IoYXMucmFzdGVyKHJlYWRQTkcoaW1nMSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcnBvbGF0ZSA9IEZBTFNFKQogIGltZzIgPC0gZ3JpZDo6cmFzdGVyR3JvYihhcy5yYXN0ZXIocmVhZFBORyhpbWcyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVycG9sYXRlID0gRkFMU0UpCiAgZ3JpZC5hcnJhbmdlKGltZzEsIGltZzIsIG5jb2wgPSAyLCB0b3AgPSB0ZXh0KQp9CmBgYAoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQojIGZpbmQgdGhlIGZvbGRlciBuYW1lcwphZ19kaXIgPC0gZmlsZS5wYXRoKG91dHB1dF9kaXIsIGxpc3QuZmlsZXMocGF0aD1vdXRwdXRfZGlyLAogICAgICAgICAgICAgICAgICAgICAgcGF0dGVybj0iXmNsaW5pY2FsLkdzZWFQcmVyYW5rZWQiKVsxXSkKZXJfZGlyIDwtIGZpbGUucGF0aChvdXRwdXRfZGlyLCBsaXN0LmZpbGVzKHBhdGg9b3V0cHV0X2RpciwKICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm49Il5FUi5Hc2VhUHJlcmFua2VkIilbMV0pCgphZyA8LSBmaWxlLnBhdGgoYWdfZGlyLCAicHZhbHVlc192c19uZXNfcGxvdC5wbmciKQplciA8LSBmaWxlLnBhdGgoZXJfZGlyLCAicHZhbHVlc192c19uZXNfcGxvdC5wbmciKQoKIyBmdW5jdGlvbiBJIGNyZWF0ZWQgdG8gZGlzcGxheSB0d28gcG5nJ3MgaW4gcGFyYWxsZWwKcGxvdF9ib3RoKGFnLCBlciwgIihhKSBBZ2dyZWdhdGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChiKSBFUiBvdmVyLWV4cHJlc3Npb24iKQpgYGAKCkZpZ3VyZSA1OiBOb3JtYWxpemVkIEVucmljaG1lbnQgU2NvcmUgYW5kIFNpZ25pZmljYW5jZSBwbG90cyBmb3IgYm90aCBtb2RlbCBkZXNpZ25zLiBfX2FfXywgQWdncmVnYXRlIG1vZGVsIGRlc2lnbiwgaWUuIGFjcm9zcyBhbGwgY2xpbmljYWwgc3VidHlwZXMgcHJlc2VudGVkIGluIHRoaXMgc3R1ZHk7ICpIRVIyKyosICpIRVIyKy9FUisqLCAqRVIrKiwgYW5kICpUTkJDKi4gX19iX18sIEVSIG92ZXItZXhwcmVzc2lvbiBzdWJ0eXBlIGNsYXNzaWZpZWQgYnkgZWl0aGVyIG92ZXItZXhwcmVzc2VkICpFUiosIG9yIGxhY2sgdGhlcmVvZi4gUHJvZHVjZWQgYnkgdGhlIEdTRUEgUHJlUmFua2VkIEFuYWx5c2lzLiBTaWduaWZpY2FuY2UgaXMgZGV0ZXJtaW5lZCB2aWEgQmVuamFtaW5pLUhvY2hiZXJnIGNvcnJlY3Rpb24gZm9yIEZhbHNlIERpc2NvdmVyeSBSYXRlLCAqcCA8IDAuMDUqLgoKPGJyLz4KCkkgcmVhZCBpbiB0aGUgcmVzdWx0aW5nIGNzdiBmaWxlcyBmcm9tIHRoZSBHU0VBIHJlcG9ydHMuCgpgYGB7cn0KYWdfbmVnIDwtIHJlYWQuY3N2MihmaWxlLnBhdGgoYWdfZGlyLCAiZ3NlYV9yZXBvcnRfZm9yX25hX25lZ18xNzQzMzg2Mjg3MTgyLnRzdiIpLAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9VFJVRSwgc2VwPSJcdCIpCmFnX3BvcyA8LSByZWFkLmNzdjIoZmlsZS5wYXRoKGFnX2RpciwgImdzZWFfcmVwb3J0X2Zvcl9uYV9wb3NfMTc0MzM4NjI4NzE4Mi50c3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsIHNlcD0iXHQiKQoKZXJfbmVnIDwtIHJlYWQuY3N2MihmaWxlLnBhdGgoZXJfZGlyLCAiZ3NlYV9yZXBvcnRfZm9yX25hX25lZ18xNzQzMzg2NTMyMjc4LnRzdiIpLAogICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9VFJVRSwgc2VwPSJcdCIpCmVyX3BvcyA8LSByZWFkLmNzdjIoZmlsZS5wYXRoKGVyX2RpciwgImdzZWFfcmVwb3J0X2Zvcl9uYV9wb3NfMTc0MzM4NjUzMjI3OC50c3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPVRSVUUsIHNlcD0iXHQiKQpgYGAKCkkgZGlzcGxheSB0aGUgdG9wIGhpdHMgZm9yIGJvdGggbW9kZWxzLCBib3RoIHBvc2l0aXZlbHkgYW5kIG5lZ2F0aXZlbHkgY29ycmVsYXRlZC4KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KaGVhZChhZ19uZWckTkFNRSkgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDQ6IE5lZ2F0aXZlbHkgY29ycmVsYXRlZCB0b3AgZ2VuZS1zZXQgaGl0cyBmb3IgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiBhY3Jvc3MgSEVSMissIEhFUjIrL0VSKywgRVIrLCBhbmQgVE5CQy4iLCBkaWdpdHM9NCkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQpoZWFkKGFnX3BvcyROQU1FKSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgNTogUG9zaXRpdmVseSBjb3JyZWxhdGVkIHRvcCBnZW5lLXNldCBoaXRzIGZvciBhZ2dyZWdhdGUgbW9kZWwgZGVzaWduIGFjcm9zcyBIRVIyKywgSEVSMisvRVIrLCBFUissIGFuZCBUTkJDLiIsIGRpZ2l0cz00KSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CmhlYWQoZXJfbmVnJE5BTUUpICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA2OiBOZWdhdGl2ZWx5IGNvcnJlbGF0ZWQgdG9wIGdlbmUtc2V0IGhpdHMgZm9yIEVSIG92ZXItZXhwcmVzc2lvbiBtb2RlbCBkZXNpZ24uIiwgZGlnaXRzPTQpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KaGVhZChlcl9wb3MkTkFNRSkgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDc6IFBvc2l0aXZlbHkgY29ycmVsYXRlZCB0b3AgZ2VuZS1zZXQgaGl0cyBmb3IgRVIgb3Zlci1leHByZXNzaW9uIG1vZGVsIGRlc2lnbi4iLCBkaWdpdHM9NCkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKKiogU2hvdyBzb21lIGVucmljaG1lbnQgcGxvdHMgb2YgaW50ZXJlc3QhIC4uLgoKCl9fYV9fLCBBZ2dyZWdhdGUgbW9kZWwgZGVzaWduLCBpZS4gYWNyb3NzIGFsbCBjbGluaWNhbCBzdWJ0eXBlcyBwcmVzZW50ZWQgaW4gdGhpcyBzdHVkeTsgKkhFUjIrKiwgKkhFUjIrL0VSKyosICpFUisqLCBhbmQgKlROQkMqLiBfX2JfXywgRVIgb3Zlci1leHByZXNzaW9uIHN1YnR5cGUgY2xhc3NpZmllZCBieSBlaXRoZXIgb3Zlci1leHByZXNzZWQgKkVSKiwgb3IgbGFjayB0aGVyZW9mLiBQcm9kdWNlZCBieSB0aGUgR1NFQSBQcmVSYW5rZWQgQW5hbHlzaXMuIFNpZ25pZmljYW5jZSBpcyBkZXRlcm1pbmVkIHZpYSBCZW5qYW1pbmktSG9jaGJlcmcgY29ycmVjdGlvbiBmb3IgRmFsc2UgRGlzY292ZXJ5IFJhdGUsICpwIDwgMC4wNSouCgpodHRwOi8vbG9jYWxob3N0Ojg3ODcvZmlsZXMvcHJvamVjdHMvR1NFMTc2MDc4L2dzZWEvY2xpbmljYWwuR3NlYVByZXJhbmtlZC4xNzQzMzg2Mjg3MTgyL2VucGxvdF9NQUpPUl9QQVRIV0FZX09GX1JSTkFfUFJPQ0VTU0lOR19JTl9USEVfTlVDTEVPTFVTX0FORF9DWVRPU09MX1JFQUNUT01FX1ItSFNBLTY3OTEyMjYuNV8xLnBuZwoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQphZyA8LSBmaWxlLnBhdGgoYWdfZGlyLCAiZW5wbG90X01BSk9SX1BBVEhXQVlfT0ZfUlJOQV9QUk9DRVNTSU5HX0lOX1RIRV9OVUNMRU9MVVNfQU5EX0NZVE9TT0xfUkVBQ1RPTUVfUi1IU0EtNjc5MTIyNi41XzEucG5nIikKZXIgPC0gZmlsZS5wYXRoKGVyX2RpciwgImVucGxvdF9DRUxMLUNFTExfQURIRVNJT05fTUVESUFURURfQllfQ0FESEVSSU5fR09CUF9HT18wMDQ0MzMxXzMucG5nIikKCnBsb3RfYm90aChhZywgZXIsICIoYSkgQWdncmVnYXRlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYikgRVIgb3Zlci1leHByZXNzaW9uIikKYGBgCgpGaWd1cmUgNjogU29tZSBlbnJpY2htZW50IHBsb3RzIGZvciBib3RoIG1vZGVsIGRlc2lnbnMuIF9fYV9fLCBBZ2dyZWdhdGUgbW9kZWwgZGVzaWduLCBpZS4gYWNyb3NzIGFsbCBjbGluaWNhbCBzdWJ0eXBlcyBwcmVzZW50ZWQgaW4gdGhpcyBzdHVkeTsgKkhFUjIrKiwgKkhFUjIrL0VSKyosICpFUisqLCBhbmQgKlROQkMqLiBQcmVzZW50ZWQgaXMgdGhlIGVucmljaG1lbnQgcGxvdCBmb3IgclJOQSBwcm9jZXNzaW5nIGluIHRoZSBudWNsZXVzIGFuZCBjeXRvc29sIHJlYWN0b21lLiBfX2JfXywgRVIgb3Zlci1leHByZXNzaW9uIHN1YnR5cGUgY2xhc3NpZmllZCBieSBlaXRoZXIgb3Zlci1leHByZXNzZWQgKkVSKiwgb3IgbGFjayB0aGVyZW9mLiBQcmVzZW50ZWQgaXMgdGhlIGVucmljaG1lbnQgcGxvdCBvZiBjZWxsLWNlbGwgYWRoZXNpb24gbWVkaWF0ZWQgY2FkaGVyaW4gYmluZGluZy4gUHJvZHVjZWQgYnkgdGhlIEdTRUEgUHJlUmFua2VkIEFuYWx5c2lzLiBTdGF0aXN0aWNzIGFuZCBtZXRyaWNzIGFyZSBkZXNjcmliZWQgb24gdGhlIEdTRUEgd2Vic2l0ZS4KCjxici8+CgojIyBIb3cgZG8gdGhlc2UgcmVzdWx0cyBjb21wYXJlIHRvIHRoZSByZXN1bHRzIGZyb20gdGhlIHRocmVzaG9sZGVkIGFuYWx5c2lzIGluIEFzc2lnbm1lbnQgMj8gQ29tcGFyZSBxdWFsaXRhdGl2ZWx5LgoKYEludGVyZmVyb25zYCBhbmQgYGNhZGhlcmluLWJpbmRpbmdgIGFyZSBmYW1pbGlhciB0ZXJtcyBmcm9tIGFzc2lnbm1lbnQgMi4gQWx0aG91Z2ggdGhlIGRlcHRoIG9mIGRldGFpbCB3ZSBhY2hpZXZlZCB3YXMgbXVjaCBsZXNzIGluIGFzc2lnbm1lbnQgMiwgYW5kIG5vdCBvbmx5IHRoYXQsIHdlIGhhZCBsZXNzIHNjb3BlIGR1ZSB0byB0aGUgdGhyZXNob2xkcyBvbiBvdXIgZ2VuZS1zZXRzLiBUaGVyZSBhcmUgc29tZSBzaW1pbGFyaXRpZXMsIGFuZCBzb21lIGRpZmZlcmVuY2VzLCB3aGljaCBpcyB0byBiZSBleHBlY3RlZC4KCiMjIyBJcyB0aGlzIGEgc3RyYWlnaHQgZm9yd2FyZCBjb21wYXJpc29uPyBXaHkgb3IgV2h5IG5vdD8KCk5vLCBzaW5jZSB0aGUgdmVyc2lvbnMgb2YgZGF0YSB3ZSBhcmUgdXNpbmcgaXMgZGlmZmVyZW50LiBBbHNvLCB0aGUgdGhyZXNob2xkZWQgYW5hbHlzaXMgZG9lcyBub3QgY29udGFpbiBhcyBtdWNoIGluZm9ybWF0aW9uLCBhbmQgYWx0aG91Z2ggd2UgaGF2ZSBnZW5lLXNldCBzaXplIGluZm9ybWF0aW9uIGF2YWlsYWJsZSBpbiBvdXIgbm9uLXRocmVzaG9sZGVkIGFuYWx5c2lzIHJlc3VsdHMsIGl0IGlzIG5vdCBzdHJhaWdodC1mb3J3YXJkLgoKIyBWaXN1YWxpemluZyBHZW5lLVNldCBFbnJpY2htZW50IEFuYWx5c2lzIGluIEN5dG9zY2FwZQoKU2ltaWxhcmx5IHRvIG91ciBhbmFseXNpcyB1c2luZyBHU0VBLCB3ZSB3aWxsIHBlcmZvcm0gb3VyIGFuYWx5c2lzIHVzaW5nIEN5dG9zY2FwZSB2aWEgUiBjb2RlLgoKVGhlIGNvZGUgYmVsb3cgaXMgYWRhcHRlZCBmcm9tIFJ1dGggSXNzZXJsaW4gW0ByaXNzZXJsaW5jeXRvXS4KCldlIGVuc3VyZSB0byB1c2UgdGhlIG9yaWdpbmFsIGdlbmUtbWF0cml4IHRyYW5zcG9zZWQgZmlsZSBzbyBhcyBub3QgdG8gaGluZGVyIG91ciBhbmFseXNpcyB3aXRoIHRoZSBmaWx0ZXJpbmcgcHJlc2VudCBpbiB0aGUgb3V0cHV0IGAuZ210YCBmcm9tIGBHU0VBYC4KCmBgYHtyfQojdXNlIHRoZSBub24tZmlsdGVyZWQgZ210CmdtdF9maWxlcyA8LSBsaXN0LmZpbGVzKHBhdGggPSBvdXRwdXRfZGlyLCBwYXR0ZXJuID0gIlxcLmdtdCIpCiMgZ2V0IHRoZSBkZXRhaWxzIG9uIHRoZSBmaWxlcwpkZXRhaWxzID0gZmlsZS5pbmZvKGZpbGUucGF0aChvdXRwdXRfZGlyLGdtdF9maWxlcykpCiMgb3JkZXIgZnJvbSBuZXdlc3QgdG8gb2xkZXN0CmRldGFpbHMgPSBkZXRhaWxzW3dpdGgoZGV0YWlscywgb3JkZXIoYXMuUE9TSVhjdChtdGltZSksZGVjcmVhc2luZyA9IFRSVUUpKSwgXQojdXNlIHRoZSBuZXdlc3QgZmlsZToKZ210X2dzZWFfZmlsZSA8LSByb3cubmFtZXMoZGV0YWlscylbMV0KYGBgCgpgYGB7cn0KYWdfZWRiIDwtIGZpbGUucGF0aChhZ19kaXIsICJlZGIiKQplcl9lZGIgPC0gZmlsZS5wYXRoKGVyX2RpciwgImVkYiIpCgphZ19yZXNfZWRiIDwtIGZpbGUucGF0aChhZ19lZGIsICJyZXN1bHRzLmVkYiIpCmVyX3Jlc19lZGIgPC0gZmlsZS5wYXRoKGVyX2VkYiwgInJlc3VsdHMuZWRiIikKCmFnX3JhbmtzIDwtIGZpbGUucGF0aChhZ19lZGIsICJhZ19yYW5rcy5ybmsiKQplcl9yYW5rcyA8LSBmaWxlLnBhdGgoZXJfZWRiLCAiZXJfcmFua3Mucm5rIikKYGBgCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KIyBidWlsZCB0aGUgY2xhc3MgZmlsZSBmb3IgYWdncmVnYXRlIGRlc2lnbgphZ19jbHMgPSAifi9wcm9qZWN0cy9HU0UxNzYwNzgvYWcuY2xzIgppZiAoIWZpbGUuZXhpc3RzKGFnX2NscykpIHsKICAjIG51bSBvZiBzYW1wbGVzIG9mIGVhY2ggY2xhc3MKICBjYXQoYXMuY2hhcmFjdGVyKHN1YnR5cGVfY291bnRzWzE6NCwxXSksc2VwID0gIiAiLGZpbGU9YWdfY2xzLGFwcGVuZD1UUlVFKQogIGNhdCgiXG4iLCBmaWxlPWFnX2NscywgYXBwZW5kPVRSVUUpCiAgIyBuYW1lcyBvZiBlYWNoIGNsYXNzCiAgY2F0KGMoIiMiLCAiSEVSMisiLCAiSEVSMisvRVIrIiwgIlROQkMiLCAiRVIrIiksIHNlcCA9ICIgIixmaWxlPWFnX2NscyxhcHBlbmQ9VFJVRSkKICBjYXQoIlxuIiwgZmlsZT1hZ19jbHMsIGFwcGVuZD1UUlVFKQogICMgb3JkZXJlZCBuYW1lIGZvciBlYWNoIHNhbXBsZQogIGNhdCh0eXBlc19kZiRzdWJ0eXBlLCBzZXAgPSAiICIsZmlsZT1hZ19jbHMsYXBwZW5kPVRSVUUpCiAgY2F0KCJcbiIsIGZpbGU9YWdfY2xzLCBhcHBlbmQ9VFJVRSkKfQpgYGAKCldlIG11c3QgZW5zdXJlIGN5dG9zY2FwZSBpcyBydW5uaW5nIGZvciB0aGUgbmV4dCBzZWN0aW9ucyBvZiBjb2RlLiBJZiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgcHJvcGVybHksIHRoZXJlIHdpbGwgYmUgYSBzdWNjZXNzZnVsIG1lc3NhZ2UgZnJvbSBDeXRvc2NhcGUgYWZ0ZXIgd2UgcGluZyEKCmBgYHtyfQojIGRlZmluZSBkb2NrZXIgYmFzZSB1cmwncwpjdXJyZW50X2Jhc2UgPSAiaG9zdC5kb2NrZXIuaW50ZXJuYWw6MTIzNC92MSIKLmRlZmF1bHRCYXNlVXJsIDwtICJodHRwOi8vaG9zdC5kb2NrZXIuaW50ZXJuYWw6MTIzNC92MSIKCmN5dG9zY2FwZVBpbmcoYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCmBgYAoKV2UgYXJlIGN1cnJlbnRseSB1c2luZyBgQ3l0b3NjYXBlYCB2ZXJzaW9uIF9fYHIgY3l0b3NjYXBlVmVyc2lvbkluZm8oYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpYF9fLgoKYGBge3J9CiMgZnVuY3Rpb24gdG8gdXBsb2FkIGEgbG9jYWwgZmlsZSB0byB0aGUgaG9zdCBtYWNoaW5lCnRvX2N5dG9zY2FwZSA8LSBmdW5jdGlvbihsb2NhbF9wYXRoKSB7CiAgYm5hbWUgPC0gYmFzZW5hbWUobG9jYWxfcGF0aCkKICByIDwtIFBPU1QoCiAgICB1cmwgPSAKcGFzdGUoJ2h0dHA6Ly9ob3N0LmRvY2tlci5pbnRlcm5hbDoxMjM0L2VucmljaG1lbnRtYXAvdGV4dGZpbGV1cGxvYWQ/ZmlsZU5hbWU9JywgCiAgICAgICAgICAgICAgICBibmFtZSwgc2VwPSIiKSwKICAgIGNvbmZpZyA9IGxpc3QoKSwKICAgIGJvZHkgPSBsaXN0KGZpbGUgPSB1cGxvYWRfZmlsZShsb2NhbF9wYXRoKSksCiAgICBlbmNvZGUgPSAibXVsdGlwYXJ0IiwKICAgIGhhbmRsZSA9IE5VTEwKICApCiAgY29udGVudChyLCJwYXJzZWQiKSRwYXRoCn0KYGBgCgpgYGB7cn0KIyBzdGFydGluZyB3aXRoIHRoZSBhZ2dyZWdhdGUgZGVzaWduIG1vZGVsLCAKIyB1cGxvYWQgbG9jYWwgZmlsZXMgYW5kIHJlY29yZCB0aGUgaG9zdCBwYXRoCmFnX3Jlc19lZGIgPC0gdG9fY3l0b3NjYXBlKGFnX3Jlc19lZGIpCmFnX3JhbmtzIDwtIHRvX2N5dG9zY2FwZShhZ19yYW5rcykKZ210IDwtIHRvX2N5dG9zY2FwZShnbXRfZ3NlYV9maWxlKQphZ19jbHMgPC0gdG9fY3l0b3NjYXBlKGFnX2NscykKIyBleHByIGZpbGUgPwoKIyBhbmQgdXBsb2FkIGZpbGVzIGZvciB0aGUgRVIgb3Zlci1leHByZXNzaW9uIG1vZGVsCmVyX3Jlc19lZGIgPC0gdG9fY3l0b3NjYXBlKGVyX3Jlc19lZGIpCmVyX3JhbmtzIDwtIHRvX2N5dG9zY2FwZShlcl9yYW5rcykKYGBgCgojIyBDcmVhdGUgYW4gRW5yaWNobWVudCBtYXAKCmBgYHtyfQpwdmFsIDwtIDAuMDUKcXZhbCA8LSAwLjA1CnNpbSA8LSAwLjM3NQpzaW1fbWV0cmljIDwtICJDT01CSU5FRCIgIyBvciBKQUNDQVJECgphZ19uZXR3b3JrIDwtIHBhc3RlKCJhZ2dyZWdhdGUiLCBwdmFsLCBxdmFsLCBzZXA9Il8iKQoKZW1fY21kID0gcGFzdGUoJ2VucmljaG1lbnRtYXAgYnVpbGQgYW5hbHlzaXNUeXBlPSJnc2VhIiBnbXRGaWxlPScsCiAgICAgICAgICAgICAgICBnbXQsCiAgICAgICAgICAgICAgICAncHZhbHVlPScsIHB2YWwsIAogICAgICAgICAgICAgICAgJ3F2YWx1ZT0nLCBxdmFsLAogICAgICAgICAgICAgICAgJ3NpbWlsYXJpdHljdXRvZmY9Jywgc2ltLAogICAgICAgICAgICAgICAgJ2NvZWZmaWNpZW50cz0nLCBzaW1fbWV0cmljLAogICAgICAgICAgICAgICAgJ3JhbmtzRGF0YXNldDE9JywgYWdfcmFua3MsCiAgICAgICAgICAgICAgICAnZW5yaWNobWVudHNEYXRhc2V0MT0nLCBhZ19yZXNfZWRiLCAKICAgICAgICAgICAgICAgICdmaWx0ZXJCeUV4cHJlc3Npb25zPWZhbHNlJywKICAgICAgICAgICAgICAgICMgJ2V4cHJlc3Npb25EYXRhc2V0MT0nLGV4cHJlc3Npb25fZmlsZV9mdWxscGF0aCwKICAgICAgICAgICAgICAgICdjbGFzc0RhdGFzZXQxPScsIGFnX2NscywKICAgICAgICAgICAgICAgICMgJ2dtdEZpbGU9JywgZ210LAogICAgICAgICAgICAgICAgc2VwPSIgIikKCiMgZmV0Y2ggdGhlIHN1aWQgb2YgdGhlIG5ld2x5IGNyZWF0ZWQgbmV0d29yawphZ19yZXNwIDwtIGNvbW1hbmRzR0VUKGVtX2NtZCwgYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCgojIGNoZWNrIGlmIHRoZSBjbWQgd2FzIHN1Y2Nlc3NmdWwgb3IgZmFpbGVkCmlmIChncmVwbChwYXR0ZXJuPSJGYWlsZWQiLCBhZ19yZXNwKSkgewogIHBhc3RlKGFnX3Jlc3ApCn0gZWxzZSB7CiAgYWdfc3VpZCA8LSBhZ19yZXNwCn0KCmN1cnJfbmFtZXMgPC0gZ2V0TmV0d29ya0xpc3QoYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCmlmIChhZ19uZXR3b3JrICVpbiUgY3Vycl9uYW1lcykgewogIGFnX25ldHdvcmsgPC0gcGFzdGUoYWdfc3VpZCwgYWdfbmV0d29yaywgc2VwPSJfIikKfQoKcmVzcCA8LSByZW5hbWVOZXR3b3JrKHRpdGxlID0gYWdfbmV0d29yaywKICAgICAgICAgICAgICAgICAgICAgIG5ldHdvcmsgPSBhcy5udW1lcmljKGFnX3N1aWQpLAogICAgICAgICAgICAgICAgICAgICAgYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCmBgYAoKQW5kLCBmb3IgdGhlIEVSIG92ZXItZXhwcmVzc2lvbiBtb2RlbCwgSSBjcmVhdGUgYW5vdGhlciBlbnJpY2htZW50IG1hcC4KCmBgYHtyfQpwdmFsIDwtIDAuMDUKcXZhbCA8LSAwLjA1CnNpbSA8LSAwLjM3NQpzaW1fbWV0cmljIDwtICJDT01CSU5FRCIgIyBvciBKQUNDQVJECgplcl9uZXR3b3JrIDwtIHBhc3RlKCJlciIsIHB2YWwsIHF2YWwsIHNlcD0iXyIpCgplbV9jbWQgPSBwYXN0ZSgnZW5yaWNobWVudG1hcCBidWlsZCBhbmFseXNpc1R5cGU9ImdzZWEiIGdtdEZpbGU9JywKICAgICAgICAgICAgICAgIGdtdCwKICAgICAgICAgICAgICAgICdwdmFsdWU9JywgcHZhbCwgCiAgICAgICAgICAgICAgICAncXZhbHVlPScsIHF2YWwsCiAgICAgICAgICAgICAgICAnc2ltaWxhcml0eWN1dG9mZj0nLCBzaW0sCiAgICAgICAgICAgICAgICAnY29lZmZpY2llbnRzPScsIHNpbV9tZXRyaWMsCiAgICAgICAgICAgICAgICAncmFua3NEYXRhc2V0MT0nLCBlcl9yYW5rcywKICAgICAgICAgICAgICAgICdlbnJpY2htZW50c0RhdGFzZXQxPScsIGVyX3Jlc19lZGIsIAogICAgICAgICAgICAgICAgJ2ZpbHRlckJ5RXhwcmVzc2lvbnM9ZmFsc2UnLAogICAgICAgICAgICAgICAgc2VwPSIgIikKCiMgZmV0Y2ggdGhlIHN1aWQgb2YgdGhlIG5ld2x5IGNyZWF0ZWQgbmV0d29yawplcl9yZXNwIDwtIGNvbW1hbmRzR0VUKGVtX2NtZCwgYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCgojIGNoZWNrIGlmIHRoZSBjbWQgd2FzIHN1Y2Nlc3NmdWwgb3IgZmFpbGVkCmlmIChncmVwbChwYXR0ZXJuPSJGYWlsZWQiLCBlcl9yZXNwKSkgewogIHBhc3RlKGVyX3Jlc3ApCn0gZWxzZSB7CiAgZXJfc3VpZCA8LSBlcl9yZXNwCn0KCmN1cnJfbmFtZXMgPC0gZ2V0TmV0d29ya0xpc3QoYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCmlmIChlcl9uZXR3b3JrICVpbiUgY3Vycl9uYW1lcykgewogIGVyX25ldHdvcmsgPC0gcGFzdGUoZXJfc3VpZCwgZXJfbmV0d29yaywgc2VwPSJfIikKfQoKZXJfcmVzcCA8LSByZW5hbWVOZXR3b3JrKHRpdGxlID0gZXJfbmV0d29yaywKICAgICAgICAgICAgICAgICAgICAgICAgIG5ldHdvcmsgPSBhcy5udW1lcmljKGVyX3N1aWQpLAogICAgICAgICAgICAgICAgICAgICAgICAgYmFzZS51cmwgPSBjdXJyZW50X2Jhc2UpCmBgYAoKIyMjIEhvdyBtYW55IG5vZGVzIGFuZCBob3cgbWFueSBlZGdlcyBpbiB0aGUgcmVzdWx0aW5nIG1hcD8KCk91ciBlbnJpY2htZW50IG1hcCBuZXR3b3JrIGZvciB0aGUgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiBhY3Jvc3MgYWxsIGZvdXIgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciBwcmVzZW50ZWQsICpIRVIyKy9FUisqLCAqSEVSMisqLCAqRVIrKiwgYW5kICpUTkJDKiwgaGFzOgoKKiAqIyBub2RlcyogOiBgMzY0YAoqICojIGVkZ2VzKiA6IGAyNzY4YAoKQW5kIHRoZSBFUiBvdmVyLWV4cHJlc3Npb24gZGVzaWduIGFjcm9zcyAqRVIrLy0qLCBoYXM6CgoqICojIG5vZGVzKiA6IGA4MmAKKiAqIyBlZGdlcyogOiBgMjAxYAoKIyMjIFdoYXQgdGhyZXNob2xkcyB3ZXJlIHVzZWQgdG8gY3JlYXRlIHRoaXMgbWFwPyAobWFrZSBzdXJlIHRvIHJlY29yZCBhbGwgdGhyZXNob2xkcykKCkkgdXNlZCB0aGUgZm9sbG93aW5nIHRocmVzaG9sZHMgZm9yIGJvdGggbmV0d29ya3M6CgoqICpwLXZhbHVlKiA6IGAwLjA1YAoqICpxLXZhbHVlKiA6IGAwLjA1YAoqICpzaW1pbGFyaXR5IHRocmVzaG9sZCogOiBgMC4zNzVgCgpJIHVzZWQgdGhlIGBDT01CSU5FRGAgc2ltaWxhcml0eSBtZXRyaWMgZm9yIHRoZXNlIG1hcHMuCgojIyMgSW5jbHVkZSBhIHNjcmVlbnNob3Qgb2YgeW91ciBuZXR3b3JrIHByaW9yIHRvIG1hbnVhbCBsYXlvdXQuCgpTaG93biBhcmUgdGhlIG5ldHdvcmtzIHByaW9yIHRvIG1hbnVhbCBsYXlvdXQuIE5vdGUgdGhhdCB0aGlzIHNlY3Rpb24gY291bGQgbm90IGJlIHByb2dyYW1tYXRpY2FsbHkgcmV0cmlldmVkIGFuZCBkaXNwbGF5ZWQgZHVlIHRvIHRoZSBsaW1pdGF0aW9ucyBvZiB1c2luZyBDeXRvc2NhcGUgaW4gUiB3aXRoIERvY2tlci4KCkJvdGggbGF5b3V0cyBhcmUgdmVyeSBtZXNzeSBiZWZvcmUgYWRqdXN0bWVudCwgYW5kIHB1cmVseSBmb3IgZGVtb25zdHJhdGl2ZSBwdXJwb3Nlcy4KCiFbRmlndXJlIDc6IEluaXRpYWwgbmV0d29yayBsYXlvdXQgZm9yIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ247ICpIRVIyKyosICpIRVIyKy9FUisqLCAqRVIrKiwgYW5kICpUTkJDKi4gR2VuZXJhdGVkIHVzaW5nIEN5dG9zY2FwZSB2aWEgUkN5My4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9pbml0aWFsX25ldHdvcmtfc3MucG5nKQoKPGJyLz4KCiFbRmlndXJlIDg6IEluaXRpYWwgbmV0d29yayBsYXlvdXQgZm9yIEVSIG92ZXItZXhwcmVzc2lvbiBtb2RlbDsgKkVSKy8tKi4gR2VuZXJhdGVkIHVzaW5nIEN5dG9zY2FwZSB2aWEgUkN5My4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9lcl9pbml0LnBuZykKCjxici8+CgoKIyMgQW5ub3RhdGUgeW91ciBOZXR3b3JrCgpBbm5vdGF0aW5nIHRoZSBuZXR3b3JrIGlzIHdoZXJlIHRoZSBtYW51YWwgd29yayBiZWdpbnMgYW5kIHRoZSBmaWd1cmVzIHN0YXJ0IHRvIGxvb2sgcmVhZGFibGUuCgojIyMgV2hhdCBwYXJhbWV0ZXJzIGRpZCB5b3UgdXNlIHRvIGFubm90YXRlIHRoZSBuZXR3b3JrPyAobWFrZSBzdXJlIHRvIGxpc3QgdGhlIGRlZmF1bHQgcGFyYW1ldGVycyB5b3UgYXJlIHVzaW5nIGFzIHdlbGwpCgpJIGFkZGVkIGEgY2xhc3MgZmlsZSBpbiB0aGUgR1NFQSBmb3JtYXQgdG8gYWRkIGluZm9ybWF0aW9uIGFib3V0IGVhY2ggc2FtcGxlJ3MgY2xhc3NpZmljYXRpb24gYWNjb3JkaW5nIHRvIHRoZSBhZ2dyZWdhdGUgY2xpbmljYWwgc3VidHlwZSBkZXNpZ24sIGhvd2V2ZXIgSSBkaWQgbm90IHJlYWxseSBzZWUgaXQgcHJlc2VudCBpbiB0aGUgbmV0d29yay4KCkkgdXNlZCB0aGUgYEF1dG9Bbm5vdGF0ZWAgYWRkaXRpb25hbCBhcHBsaWNhdGlvbiB0byBhbm5vdGF0ZSB1c2luZyBgR2VuZS1TZXQgRGVzY3JpcHRpb25zYC4gSSBzZWxlY3RlZCB0aGUgJ0xheW91dCBOZXR3b3JrIHRvIGF2b2lkIGNsdXN0ZXIgb3ZlcmxhcCcgYW5kIGFkanVzdGVkIHNvbWUgb2YgdGhlIGxhYmVscyB0aGF0IHdlcmUgb3ZlcmxhcHBpbmcuCgpUaGUgbm9kZXMgYXJlIGNvbG91ci1zY2FsZWQgYnkgYEZEUiBxLXZhbHVlYCB3aXRoIGRhcmtlci1yZWQgbm9kZXMgaGF2aW5nIHZhbHVlcyBjbG9zZXIgdG8gMC4wMCwgYW5kIGxpZ2h0ZXItcmVkIG5vZGVzIGhhdmluZyB2YWx1ZXMgY2xvc2VyIHRvIDAuMDUuCgpfX0N1dC1PZmYgVmFsdWVzOl9fCgoqIFAtdmFsdWU6IDAuMDUgCiogRkRSIFEtdmFsdWU6IDAuMDUgCiogSmFjY2FyZCBPdmVybGFwIENvbWJpbmVkOiAwLjM3NSAgCiogVGVzdCB1c2VkOiBKYWNjYXJkIE92ZXJsYXAgQ29tYmluZWQgSW5kZXggKGsgY29uc3RhbnQgPSAwLjUpIAoKX19EYXRhIFNldHM6X18KCiogRGF0YXNldCAxIAoqIEdlbmUgU2V0cyBGaWxlOiAuLi4vZW1fZmlsZXVwbG9hZF8xNjEyMDYyMzkxMzIyNTY3MTg5OC9lbV8xMTE2MjI2Nzk3NDQyNzMyNzY5Nl8KSHVtYW5fR09CUF9BbGxQYXRod2F5c19ub1BGT0NSX25vX0dPX2llYV9NYXJjaF8wMV8yMDI1X3N5bWJvbC5nbXQgCiogRGF0YSBGaWxlczogLi4uL2VtX2ZpbGV1cGxvYWRfMTYxMjA2MjM5MTMyMjU2NzE4OTgvZW1fNjIwNTk5MzQ1MjMxMTUxNzYxN19yZXN1bHRzLmVkYiAKKiBSYW5rcyBGaWxlOiAuLi4vZW1fZmlsZXVwbG9hZF8xNjEyMDYyMzkxMzIyNTY3MTg5OC9lbV8xMzkyNTUyOTEwMTAwNjgyNTExMV9hZ19yYW5rcy5ybmsgCiogUG9zaXRpdmUgUGhlbm90eXBlOiBVUCAKKiBOZWdhdGl2ZSBQaGVub3R5cGU6IERPV04gCgojIyBNYWtlIGEgcHVibGljYXRpb24tcmVhZHkgZmlndXJlIHdpdGggcHJvcGVyIGxlZ2VuZHMuCgpUaGUgYW5ub3RhdGlvbnMgcHJlc2VudCBhcmUgYWxyZWFkeSBncm91cGVkIGFuZCBjbGVhcmx5IGhpZ2hsaWdodGVkLiBJIGFkZGVkIGEgbGVnZW5kIHRvIHRoZSB0b3AtbGVmdCBkZW5vdGluZyB0aGUgbm9kZSBjb2xvdXItc2NhbGluZy4gSSBzZWxlY3RlZCB0aGUgJ1B1YmxpY2F0aW9uIFJlYWR5JyBvcHRpb24gYW5kIGl0IHJlbW92ZWQgdGhlIGxhYmVscyBvZiB0aGUgaW5kaXZpZHVhbCBub2RlcyB0aGVtc2VsdmVzLCBzbyB0aGUgZm9jdXMgY2FuIGJlIGRyYXduIHRvIHRoZSBhbm5vdGF0aW9ucy4KCiFbRmlndXJlIDk6IEFubm90YXRlZCBhZ2dyZWdhdGUgbmV0d29yayBsYXlvdXQ7ICpIRVIyKyosICpIRVIyKy9FUisqLCAqRVIrKiwgYW5kICpUTkJDKi4gR2VuZXJhdGVkIHVzaW5nIEN5dG9zY2FwZSB2aWEgUkN5MywgYW5ub3RhdGVkIHVzaW5nIEF1dG9Bbm5vdGF0ZSBhcHBsaWNhdGlvbiBpbiB0aGUgQ3l0b3NjYXBlIGludGVyZmFjZS4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9wdWJfYWcucG5nKQoKPGJyLz4KCiFbRmlndXJlIDEwOiBBbm5vdGF0ZWQgRVIgb3Zlci1leHByZXNzaW9uIG5ldHdvcmsgbGF5b3V0OyAqRVIrLy0qLiBHZW5lcmF0ZWQgdXNpbmcgQ3l0b3NjYXBlIHZpYSBSQ3kzLCBhbm5vdGF0ZWQgdXNpbmcgQXV0b0Fubm90YXRlIGFwcGxpY2F0aW9uIGluIHRoZSBDeXRvc2NhcGUgaW50ZXJmYWNlLiBwLXZhbHVlIDwgMC4wNSwgcS12YWx1ZSA8IDAuMDUsIHNpbWlsYXJpdHkgdGhyZXNob2xkIDwgMC4zNzUgd2l0aCBhIGNvbWJpbmVkIHNpbWlsYXJpdHkgbWV0cmljLl0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL2VyX3B1Yi5wbmcpCgo8YnIvPgoKVGhlcmUgaXMgYSBtYWpvciBmb2N1cyBvbiB0aGUgY2VudHJhbCBncm91cGluZyB3aXRoIHNvbWUgc3BhcnNlciBub2RlcyBwcmVzZW50IG9uIHRoZSBvdXRza2lydHMgb2YgdGhlIG5ldHdvcmsuIEkgZmlsdGVyZWQgbm9kZXMgdGhhdCBkaWQgbm90IGhhdmUgbW9yZSB0aGFuIDUgY29ubmVjdGlvbnMsIGhvd2V2ZXIgdGhleSBzdGlsbCBzaG93ZWQgdXAgb24gdGhlIGdyYXBoIGRlc3BpdGUgYmVpbmcgaGlnaGxpZ2h0ZWQgZGlmZmVyZW50bHkgaW4gbXkgaW5pdGlhbCBuZXR3b3JrLgoKIyMgQ29sbGFwc2UgeW91ciBuZXR3b3JrIHRvIGEgdGhlbWUgbmV0d29yay4KCkZvciB0aGlzIHNlY3Rpb24sIEkgZ2VuZXJhdGVkIHR3byB0aGVtZWQgbmV0d29ya3MgZm9yIGVhY2ggb2YgdGhlIG1vZGVsIGRlc2lnbnMuCgpGaXJzdCwgSSBnZW5lcmF0ZWQgYSBzdW1tYXJ5IG5ldHdvcmsgdG8gc2hvdyBhIG1vcmUgY29uY2lzZSBhbmQgc2ltcGxlIGRlc2lnbiBoaWdobGlnaHRpbmcgdGhlIG1ham9yIGNvbm5lY3Rpb24gcG9pbnRzIGluIHRoaXMgbmV0d29yay4KCiFbRmlndXJlIDExOiBTdW1tYXJ5IHRoZW1lZCBuZXR3b3JrIGZvciBhZ2dyZWdhdGUgbW9kZWwgZGVzaWduOyAqSEVSMisqLCAqSEVSMisvRVIrKiwgKkVSKyosIGFuZCAqVE5CQyouIEdlbmVyYXRlZCB1c2luZyBDeXRvc2NhcGUgdmlhIFJDeTMsIGNsZWFuZWQgdXNpbmcgQXV0b0Fubm90YXRlIGFwcGxpY2F0aW9uIGluIHRoZSBDeXRvc2NhcGUgaW50ZXJmYWNlIHRvIGdlbmVyYXRlIGEgU3VtbWFyeSBuZXR3b3JrLiBwLXZhbHVlIDwgMC4wNSwgcS12YWx1ZSA8IDAuMDUsIHNpbWlsYXJpdHkgdGhyZXNob2xkIDwgMC4zNzUgd2l0aCBhIGNvbWJpbmVkIHNpbWlsYXJpdHkgbWV0cmljLl0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL3N1bW1hcnlfYWcucG5nKQoKPGJyLz4KCk5leHQsIEkgZ2VuZXJhdGVkIGEgY2x1c3RlcmluZyBhdCB0aGUgbW9zdCBnZW5lcmljIGxldmVsIGZvciB0aGUgYWdncmVnYXRlIGRlc2lnbiBuZXR3b3JrLiAKCgohW0ZpZ3VyZSAxMjogR2VuZXJpYyBjbHVzdGVyaW5nIG5ldHdvcmsgZm9yIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ247ICpIRVIyKyosICpIRVIyKy9FUisqLCAqRVIrKiwgYW5kICpUTkJDKi4gR2VuZXJhdGVkIHVzaW5nIEN5dG9zY2FwZSB2aWEgUkN5MywgY2xlYW5lZCB1c2luZyBBdXRvQW5ub3RhdGUgYXBwbGljYXRpb24gaW4gdGhlIEN5dG9zY2FwZSBpbnRlcmZhY2UgdG8gZ2VuZXJhdGUgdGhlIG1vc3QgZ2VuZXJpYyBjbHVzdGVyaW5nIGF2YWlsYWJsZS4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9nZW5lcmljX2FnLnBuZykKCgo8YnIvPgoKIVtGaWd1cmUgMTM6IFN1bW1hcnkgY2x1c3RlcmluZyBuZXR3b3JrIGZvciBFUiBvdmVyLWV4cHJlc3Npb24gbW9kZWwgZGVzaWduOyAqRVIrLy0qLiBHZW5lcmF0ZWQgdXNpbmcgQ3l0b3NjYXBlIHZpYSBSQ3kzLCBjbGVhbmVkIHVzaW5nIEF1dG9Bbm5vdGF0ZSBhcHBsaWNhdGlvbiBpbiB0aGUgQ3l0b3NjYXBlIGludGVyZmFjZSB0byBnZW5lcmF0ZSBhIFN1bW1hcnkgbmV0d29yay4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9lcl9zdW0ucG5nKQoKPGJyLz4KCiFbRmlndXJlIDE0OiBHZW5lcmljIGNsdXN0ZXJpbmcgbmV0d29yayBmb3IgRVIgb3Zlci1leHByZXNzaW9uIG1vZGVsIGRlc2lnbjsgKkVSKy8tKi4gR2VuZXJhdGVkIHVzaW5nIEN5dG9zY2FwZSB2aWEgUkN5MywgY2xlYW5lZCB1c2luZyBBdXRvQW5ub3RhdGUgYXBwbGljYXRpb24gaW4gdGhlIEN5dG9zY2FwZSBpbnRlcmZhY2UgdG8gZ2VuZXJhdGUgdGhlIG1vc3QgZ2VuZXJpYyBjbHVzdGVyaW5nIGF2YWlsYWJsZS4gcC12YWx1ZSA8IDAuMDUsIHEtdmFsdWUgPCAwLjA1LCBzaW1pbGFyaXR5IHRocmVzaG9sZCA8IDAuMzc1IHdpdGggYSBjb21iaW5lZCBzaW1pbGFyaXR5IG1ldHJpYy5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9lcl9nZW4ucG5nKQoKPGJyLz4KCiMjIyBXaGF0IGFyZSB0aGUgbWFqb3IgdGhlbWVzIHByZXNlbnQgaW4gdGhpcyBhbmFseXNpcz8KClByZXR0eSBjbGVhcmx5IGZvciB0aGUgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiwgdGhlIG1ham9yIHRoZW1lIGlzIHByb3RlaW4gc3ludGhlc2lzIHByb2Nlc3Nlcy4gVGhlIG1vc3QgZ2VuZXJpYyBsZXZlbCBvZiBncm91cGluZyBoYWQgbm8gcmVhbCBlZmZlY3Qgb24gdGhlIG5vZGVzIHNlZW1pbmdseSBzZXBhcmF0ZSBmcm9tIHRoZSBtb3N0IGNlbnRyYWwgZ3JvdXBpbmcsIGFuZCBzbyBncm91cGVkIHRoZSBtb3N0IHJlbGF0ZWQgZ2VuZS1zZXRzIGludG8gYFByb3RlaW4gU3ludGhlc2lzIFByb2Nlc3Nlc2AuCgpUaGlzIHBhcnRpY3VsYXIgZ3JvdXBpbmcgbWFqb3JseSBjb21iaW5lcyBgU1JQIFByb3RlaW4gU3ludGhlc2lzYCwgYE51Y2xlYXIgRXhwb3J0IFN1bW95bGF0aW9uYCwgYFByb2Nlc3MgUHVyaW5lIENhdGFib2xpc21gLCBhbmQgYFN0cmFuZCBETkEgVGVtcGxhdGluZ2AsIGFsb25nIHdpdGggYGRlIG5vdm8gZm9sZGluZ2AsIGBzbWFsbCBzdWJ1bml0IGFzc2VtYmx5YCwgYFRyaWNpc3Ryb25pYyByUk5BIFNTVWAsIGFtb25nIGEgZmV3IG90aGVycy4KCkFwYXJ0IGZyb20gdGhpcyBtYWpvciB0aGVtZSwgdGhlIHNlcGFyYXRlIGdyb3VwcyBhcmUgZmFpcmx5IHNlcGFyYXRlLCBhbHRob3VnaCBzb21lIHBvc3NpYmxlIG1lY2hhbmlzbXMgcHJlc2VudCB0aGVtc2VsdmVzIGFzIGludGVyZXN0aW5nLCBzdWNoIGFzIHRoZSByZWxhdGlvbiBvZiBgVGh5bWljIElMMiAxIFBhdGh3YXlgIGFuZCBgU3BpbmRsZSBDaGVja3BvaW50IENocm9tb3NvbWVgIHRvIGJyZWFzdCBjYW5jZXJvdXMgc3VidHlwZSBkaWZmZXJlbmNlcy4KCjxici8+CgpGb3IgdGhlIEVSIG92ZXItZXhwcmVzc2lvbiBtb2RlbCBkZXNpZ24sIHRoZSBtYWpvciB0aGVtZSBhcHBlYXJzIHRvIGJlIHRoZSBgRWxlY3Ryb24gVHJhbnNwb3J0IFByb2Nlc3NgLCBhbG9uZyB3aXRoIGBQaG9zcGhvbGlwaWQgUGhhZ29jeXRvc2lzYCBhbmQgYFN0cmFuZCBOdWNsZWFyIEROQWAuCgpgRWxlY3Ryb24gVHJhbnNwb3J0IFByb2Nlc3NgIGdyb3VwcyBgR2x5Y29nZW5lc2lzIFR5cGUgRGVmaWNpZW5jeWAsIGBQcm9jZXNzIERpcGhvc3BoYXRlIE1ldGFib2xpY2AsIGFuZCBgQ291cGxlZCBFbGVjdHJvbiBUcmFuc3BvcnRgLgoKIyMjIERvIHRoZXkgZml0IHdpdGggdGhlIG1vZGVsPwoKSXQgaXMgbm90IHZlcnkgaW5mb3JtYXRpdmUgdG8gc2F5IHRoYXQgYFByb3RlaW4gU3ludGhlc2lzIFByb2Nlc3Nlc2AgZml0IGFzIGEgZGV0ZXJtaW5hdGlvbiBpbiBkaXN0aW5ndWlzaGluZyBkaWZmZXJlbnQgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlci4gKkhFUjIqIGFuZCAqRVIqIG92ZXItZXhwcmVzc2lvbiBvciBsYWNrIHRoZXJlb2YgY2xhc3NpZnkgdGhlc2Ugc3VidHlwZXMsIGFuZCBzbyBpdCBzZWVtcyBuYXR1cmFsIHRoYXQgcHJvdGVpbiBzeW50aGVzaXMgaXMgaW52b2x2ZWQuCgpTaW1pbGFybHksIHRoZSBgRWxlY3Ryb24gVHJhbnNwb3J0IFByb2Nlc3NgIGlzIGhhbGxtYXJrIHRvIHRoZSBlbnRpcmV0eSBvZiBjZWxsdWxhciBmdW5jdGlvbi4gQXMgdG8gaG93IGl0IGZpdHMgd2l0aCAqRVIqIG92ZXItZXhwcmVzc2lvbiBvciBsYWNrIHRoZXJlb2YgaW4gYnJlYXN0IGNhbmNlcm91cyBzdWJ0eXBlcyBpcyB1bmtub3duLgoKIyMjIEFyZSB0aGVyZSBhbnkgbm92ZWwgcGF0aHdheXMgb3IgdGhlbWVzPwoKVGhlcmUgYXJlIHNvbWUgbm92ZWwgcGF0aHdheXMgYW5kIHRoZW1lcywgbGlrZSB0aGF0IG9mIGBUaHltaWMgSUwyIDEgUGF0aHdheWAgYW5kIGBTcGluZGxlIENoZWNrcG9pbnQgQ2hyb21vc29tZWAgd2hpY2ggY2FuIGJlIGFzc29jaWF0ZWQgd2l0aCBwb3NzaWJsZSBtZWNoYW5pc21zIG9mIGJyZWFzdCBjYW5jZXIuIEFzIHRvIGhvdyB0aGVzZSBzZXBhcmF0ZSB0aGUgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciBpcyBub3ZlbCwgYnV0IHBvc3NpYmxlLiBJbnRlcmxldWtpbiBpbmZsYW1tYXRpb24gY2FuIGNvbnRyaWJ1dGUgdG8gZW52aXJvbm1lbnRzIGNvbmR1Y2l2ZSB0byBjYW5jZXJvdXMgZ3Jvd3RoIGFuZCBwcm9saWZlcmF0aW9uLCBzaW1pbGFybHkgd2l0aCBwcm9ibGVtcyBpbiB0aGUgY2VsbCBjeWNsZSBsaWtlIHRoYXQgb2Ygc3BpbmRsZSBjaGVja3BvaW50KHMpLgoKYFNraW4gRXBpZGVybWlzIERldmVsb3BtZW50YCBzZWVtcyBxdWl0ZSBmYXIgb2ZmIGZyb20gYnJlYXN0IGNhbmNlci4gSSBhbSBhc3N1bWluZyBtZXRhc3Rhc2VzIGNhbiBiZSBjb21tb24gZm9yIG9uZSByZWFzb24gb3IgYW5vdGhlciwgYnV0IGl0IGlzIHZlcnkgZGlmZmljdWx0IHRvIGNoYXJhY3Rlcml6ZSB0aGlzIHNtYWxsIGdyb3VwaW5nIGFzIGJlaW5nIHJlbGF0ZWQgdG8gdGhlIGNsaW5pY2FsIHN1YnR5cGVzIG9mIG91ciBpbnRlcmVzdC4KCkZvciB0aGUgRVIgb3Zlci1leHByZXNzaW9uLCBpdCBzZWVtcyBtb3N0IG9mIHRoZSBwYXRod2F5cywgZXZlbiBkZXNwaXRlIGhhdmluZyBvbmx5IGEgZmV3IG5vZGVzLCBhcmUgcmF0aGVyIHJlbGV2YW50IHRvIHRoZSByZWxhdGl2ZSByZWFsbSBvZiBicmVhc3QgY2FuY2Vyb3VzIHBhdGhvbG9neS4KCiMgSW50ZXJwcmV0YXRpb24KCiMjIERvIHRoZSBlbnJpY2htZW50IHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc21zIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/CgpUaGUgb3JpZ2luYWwgcGFwZXIgaW5jbHVkZWQgdGhpcyBlbnJpY2htZW50IGFuYWx5c2lzIG9mIHRoZWlyIHNpbmdsZS1jZWxsIFJOQSBzZXF1ZW5jaW5nIHNhbXBsZXMuIFRoaXMgR2VuZS1TZXQgRW5yaWNobWVudCBBbmFseXNpcyB3YXMgcGVyZm9ybWVkIHVzaW5nIENsdXN0ZXJQcm9maWxlciB3aXRoIGdlbmUtc2V0cyBmcm9tIHRoZSBNU2lnREIgSEFMTE1BUksgY29sbGVjdGlvbi4gKnAtdmFsdWVzIDwgMC4wNSogd2VyZSBhZGp1c3RlZCB1c2luZyBCb25mZXJyb25pLgoKIVtGaWd1cmUgMTU6IEdlbmUtU2V0IEVucmljaG1lbnQgQW5hbHlzaXMgcGVyZm9ybWVkIGJ5IHRoZSBvcmlnaW5hbCBwdWJsaXNoZXJzIFd1LiBldCBhbCAoMjAyMSldKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9vZ19wYXBlci5wbmcpCgo8YnIvPgoKTXkgYWdncmVnYXRlIG1vZGVsIGRlc2lnbiBzb2xlbHkgYWdyZWVzIHdpdGggdGhlIGZpbmRpbmdzIG9mIHRoZSBwdWJsaWNhdGlvbiBvbiBgTWl0b3RpYyBTcGluZGxlYC4gVGhlIHJlbWFpbmRlciBvZiBteSBuZXR3b3JrIGRvZXMgbm90IGFncmVlIHdpdGggdGhlIGZpbmRpbmdzIHdoYXRzb2V2ZXIuCgpTaW1pbGFybHksIG15IEVSIG92ZXItZXhwcmVzc2lvbiBkZXNpZ24gbGlzdHMgYEhhbGxtYXJrIEludGVyZmVyb24gUmVzcG9uc2VgIGluIGFncmVlbWVudCB3aXRoIHRoZSBwdWJsaWNhdGlvbi4gT3RoZXIgdGhhbiB0aGF0LCB0aGVyZSBpcyBsaXR0bGUgYWdyZWVtZW50LgoKIyMjIEhvdyBkbyB0aGVzZSByZXN1bHRzIGRpZmZlciBmcm9tIHRoZSByZXN1bHRzIHlvdSBnb3QgaW4gQXNzaWdubWVudCAyIHRocmVzaG9sZGVkIG1ldGhvZHM/CgpJbiBhc3NpZ25tZW50IDIsIG15IGVucmljaG1lbnQgcmVzdWx0cyBtZW50aW9uZWQgYEludGVyZmVyb25zYCwgYW5kIGBDYWRoZXJpbi1iaW5kaW5nYCwgYnV0IG5vdGhpbmcgZWxzZSBpcyB0b28gc2ltaWxhci4gQXBhcnQgZnJvbSB0aGUgdmVyeSBnZW5lcmljIGNvbmNsdXNpb25zIGJlaW5nIGBQcm90ZWluIFN5bnRoZXNpcyBQcm9jZXNzZXNgIGFuZCBgRWxlY3Ryb24gVHJhbnNwb3J0IFByb2Nlc3Nlc2AuCgojIyBDYW4geW91IGZpbmQgZXZpZGVuY2UsIGllLiBwdWJsaWNhdGlvbnMsIHRvIHN1cHBvcnQgc29tZSBvZiB0aGUgcmVzdWx0cyB0aGF0IHlvdSBzZWU/CgpOb3QgY29uY2x1c2l2ZWx5LiBBbHRob3VnaCB0aGVyZSBpcyBhbHdheXMgY29ycmVsYXRpdmUgZXZpZGVuY2UsIGVzcGVjaWFsbHkgaW4gYSBmaWVsZCBzbyByZXNlYXJjaGVkIGFzIGJyZWFzdCBjYW5jZXIsIEkgZG8gbm90IGJlbGlldmUgdGhlIGV2aWRlbmNlIGlzIHN1YnN0YW50aWFsIGVub3VnaCB0byByZWFsbHkgc2F5IGFueXRoaW5nIGF0IHRoaXMgcG9pbnQuIFRoZSBuZXR3b3JrIG91dGNvbWVzIGFyZSB0b28gZ2VuZXJpYyBmb3IgYW55IGNvbmNsdXNpb25zIHRvIGJlIGRyYXduIGZyb20gdGhpcy4KCiMjIyBIb3cgZG9lcyB0aGUgZXZpZGVuY2Ugc3VwcG9ydCB5b3VyIHJlc3VsdD8KCkkgc3RydWdnbGVkIHRvIGZpbmQgZXZpZGVuY2UgdG8gc3VwcG9ydCB0aGVzZSByZXN1bHRzIHNpbmNlIHRoZXkgYXJlIHNvIGdlbmVyaWMuCgojIERldGFpbGVkIFZpZXcgb2YgUmVzdWx0cwoKSSBjaG9zZSB0byBhbmFseXplIHRoZSB0aHJlZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBpbiB0aGUgRVIgb3Zlci1leHByZXNzaW9uIG1vZGVsOiAqQU5YQTgqLCAqTUtYKiwgYW5kICpDRDIwNyouCgpJIGZvdW5kIGEgbmV0d29yayBjb250YWluaW5nIGJvdGggKkFOWEE4KiBhbmQgKkNEMjA3KiB1bmRlciB0aGUgZXBpZGVybWlzIGRldmVsb3BtZW50IEdPIGJpb2xvZ2ljYWwgcHJvY2Vzcy4KCiFbRmlndXJlIDE2OiBOZXR3b3JrIGZvciBlcGlkZXJtaXMgZGV2ZWxvcG1lbnQgd2hpY2ggaW5jbHVkZXMgYm90aCBBTlhBOCBhbmQgQ0QyMDc7IHR3byBvZiB0aGUgdGhyZWUgc2lnbmlmaWNhbnQgZ2VuZXMgaW4gRVIgb3Zlci1leHByZXNzaW9uLiBQdWxsZWQgYnkgdXNpbmcgdGhlIFNUSVRDSCBwcm90ZWluIHF1ZXJ5IG9uIHRoZSByZXNwZWN0aXZlIGdlbmVzIG9mIGludGVyZXN0IG9uIEN5dG9zY2FwZS5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9leHRyYS5wbmcpCgpUaGV5IGludGVyYWN0IHRocm91Z2ggaHNhLW1pci0yMDUsIHdoaWNoIGlzIGEgbWljcm8gUk5BLiBBY2NvcmRpbmcgdG8gaXRzIGFzc29jaWF0ZWQgZ2VuZSBjYXJkIFtAbWlybmFdLCBpdCBpcyBhc3NvY2lhdGVkIHdpdGggc3F1YW1vdXMgY2VsbCBjYXJjaW5vbWEgaW4gdGhlIGhlYWQgYW5kIG5lY2suIFRoaXMgaXMgYW4gaW50ZXJlc3RpbmcgYXNzb2NpYXRpb24sIGFuZCBub3QgZmFyIG9mZiBmcm9tIGJyZWFzdCBjYW5jZXIsIGFsdGhvdWdoIGEgc3RyZXRjaCBmb3Igc3VyZS4KCkxvb2tpbmcgZnVydGhlciBpbnRvIHNxdWFtb3VzIGJyZWFzdCBjYW5jZXJvdXMgdGlzc3VlcyBicm91Z2h0IG1lIHRvIHRoaXMgU3RyaW5nIG5ldHdvcmsuCgohW0ZpZ3VyZSAxNzogU3RyaW5nIE5ldHdvcmsgZm9yIHNxdWFtb3VzIGNhcmNpbm9tYSBpbiBicmVhc3QgdGlzc3VlLiBQdWxsZWQgYnkgdXNpbmcgdGhlIFNUSVRDSCBkaXNlYXNlIHF1ZXJ5IG9uIHNxdWFtb3VzIGNhcmNpbm9tYS5dKC9ob21lL3JzdHVkaW8vcHJvamVjdHMvZmlndXJlcy9zcWEucG5nKQoKTm90YWJseSwgKkVSQkIyKiBpcyBwcmVzZW50IGluIHllbGxvdy4gVGhpcyBpcyB0aGUgZGVmaW5pdGlvbiBvZiBleHByZXNzaW9uIG9mICpIRVIyKiwgYW5kIHNvIGl0cyByZWxhdGlvbiB0byBzcXVhbW91cyBjYXJjaW5vbWEgaW4gYnJlYXN0IGNhbmNlcm91cyB0aXNzdWUgaXMgdmVyeSBpbnRlcmVzdGluZy4gQWRkaXRpb25hbGx5LCB3ZSBzZWUgQlJDQTEsIGEgY2xhc3NpYywgYW5kIE1VQzEsIHdoaWNoIHdhcyBpbiBvdXIgYWdncmVnYXRlIG1vZGVsIGRlc2lnbi4KCiMgQXNzb2NpYXRlZCBKb3VybmFsIEVudHJ5CgpNeSBhc3NvY2lhdGVkIGpvdXJuYWwgZW50cnkgd2lraSBsaW5rIGZvciB0aGlzIGFzc2lnbm1lbnQgaXMgW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9iY2I0MjAtMjAyNS9Bbm5hYmVsbGFfQnJlZ2F6emkvd2lraS9Bc3NpZ25tZW50LTMpLgoKIyBBY2tub3dsZWRnbWVudHMKClRoaXMgcGFwZXIgbWFrZXMgdXNlIG9mIHBhY2thZ2VzIGBrbml0cmAgW0Brbml0cjIwMTVdLCBgQmlvY01hbmFnZXJgIFtAYmlvY21hbmFnZXJdLCBgR0VPcXVlcnlgIFtAUi1HRU9xdWVyeV0sIGBrYWJsZUV4dHJhYCBbQGthYmxlZXh0cmFdLCBgZWRnZVJgIFtAUi1lZGdlUl0sIGBsaW1tYWAgW0BsaW1tYTIwMTVdLCBgQ29tcGxleEhlYXRtYXBgIFtAY29tcGxleGhlYXRtYXBdLCBgY2lyY2xpemVgIFtAY2lyY2xpemVdLCBgZ3Byb2ZpbGVyMmAgW0BncHJvZmlsZXIyXSwgYEdTQWAgW0Bnc2FdLCBgcmN1cmxgIFtAcmN1cmxdLCBgZ2dwbG90MmAgW0BSLWdncGxvdDJdLCBgZ3JpZGAgW0BncmlkXSwgYGdyaWRFeHRyYWAgW0BncmlkRXh0cmFdLCBgcG5nYCBbQHBuZ10sIGBSQ3kzYCBbQHJjeTNdLCAmIGBodHRyYCBbQGh0dHJdLgoKIyBCaWJsaW9ncmFwaHk=